Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8cc codegen is accessing (potentially) uninitialized struct fields #67

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

kiwidrew
Copy link

When using a malloc() implementation that doesn't clear the memory region (which is permitted behaviour according to the standards) it is quite easy for 8cc to generate invalid assembly code. I first noticed this issue when compiling 8cc under OpenBSD, which has a malloc() implementation that does not always clear memory before allocating it to the user program.

The symptom was maybe_emit_bitshift_load() and maybe_emit_bitshift_save() generating bogus SHR and SHL instructions when the bitsize field (signed int32) is less than or equal to zero, which happens frequently when referencing memory which hasn't been cleared. Thankfully GNU as caught the issue and aborted without generating an object file.

To be safe, I've changed all malloc(size) calls to use calloc(nmemb, size) instead.

kiwidrew added 2 commits June 25, 2015 12:27
typically initialized;  these fields are only assigned values for actual
bitfield members.  However, the 'maybe_emit_bitshift_load' and
'maybe_emit_bitshift_save' functions (called by 'emit_[gl]{load,save}'
functions) access these fields unconditionally.

Simple fix is to replace malloc() with calloc(), which ensures that
the memory region has been cleared.

(This bug was discovered while working to port 8cc to OpenBSD, which
provides a malloc() implementation that does not necessarily clear the
memory region upon allocation.)
@rui314
Copy link
Owner

rui314 commented Jun 25, 2015

Thanks. I think we should use calloc only when needed. Your patch seems to use calloc even if an allocated memory is initialized immediately.

@andrewchambers
Copy link
Contributor

It is handy to have a sensible default for most values. If this was going to be added, It would be better style to create a wrapper around malloc which checks for errors and does the zeroing.

@kiwidrew
Copy link
Author

Just to be clear, commit 141d508 is all that is needed to avoid test case failures due to the use-before-initialization error in the Type struct. I added commit a198b17 as extra insurance, since it wasn't entirely obvious that Type was the only struct to suffer from a use-before-initialization error.

It would seem that the code (mostly) follows the standard C language convention where each struct member's "default" or uninitialized value is assumed to be zero. Replacing malloc() with calloc() merely serves to ensure that these assumptions hold true in all cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants