-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Fail cleanly on allocation failures #2223
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
Conversation
Previously code in the SWIG tool didn't handle allocation failures well. Most places didn't check for NULL return from malloc()/realloc()/calloc() at all, typically resulting in undefined behaviour, and some places used assert() to check for a NULL return (which is a misuse of assert() and such checks disappear if built with NDEBUG defined leaving us back with undefined behaviour). All C allocations are now done via wrapper functions (Malloc(), Realloc() and Calloc()) which emit and error and exit with non-zero status on failure, so a non-NULL return can be relied upon. Fixes swig#1901.
Possibly we should try to call I haven't tried that for now, mostly because that doesn't currently happen in any of the cases I've changed so my patch doesn't make that aspect worse at all. It's a bit awkward to do if we carry on with what seems to be the current assumption that DOH is a layer below SWIG which might get used elsewhere - I think we'd need to add a way to register a function with DOH which it would call on out of memory conditions. Perhaps a better alternative would be to register a cleanup function via |
Nice tidyup @ojwb. How about adding an exit function in DOH, so near the startup, SWIG registers SWIG_exit as the exit function for DOH to call in the event of an error. If the register function has not been called, then default to exit(). |
I can take a look at that, but I'll get this merged first as it's better or the same in all ways than the current code and touches quite a lot of places and so liable to conflict if left unapplied for long. I also think most if not all of the calls to The developer docs should really mention "use |
55377bd adds DOH |
735732d replaces calls to |
747a51f uses I think that completes the follow-on work here. The only other thing I wondered is whether it was worth having our own |
In 55377bd, the error count has been replaced by 1. I'm intrigued how it is possible that an int on most platforms will return 0 if the count is 256? How about keeping the error count with a ceiling of whatever the max value that will work if this is a problem? |
Sorry, I only just saw your comment @ojwb:
I wasn't aware of anything following a convention other than exiting with zero or non-zero. So new behaviour seems reasonable. |
The full background is that if you pass an
The shell exit status at least uses the traditional
Seems Microsoft copied this feature as https://docs.microsoft.com/en-us/previous-versions/6wdz5232(v=vs.140) says:
There's actually an additional complication as a process which is killed by a signal traditionally exits with status 128+signal_number:
POSIX says "Implementations are encouraged to choose exit values greater than 256 to indicate programs that terminate by a signal so that the exit status cannot be confused with an exit status generated by a normal termination" but it seems that's not caught on - I guess because it risks breaking assumptions in existing working code. So in practice values from 0 to 127 seem to be pretty portably but all C++ actually guarantees about
|
Hi @ojwb, I had some problems with the gcc poison macros when building SWIG and so have commented this bit out. See 7785377. I think it needs a rethink making sure the poison macros only apply to SWIG code and not external/system/library headers. Sorry, I've just got too much to do to have a go at fixing myself. |
Sorry, I didn't really consider this possibility but I can see the issue now. Unfortunately I don't think there's a way to say "poison but not in system headers" so we'd have to very carefully restructure the code such that the poisoning always happens after any non-SWIG headers have been included just in case a system/external header tries to reference one of these symbols. I think that's just going to end up brittle in the face of future changes though. So probably the way to go to help prevent direct calls to these functions being added in future changes is to have a CI build with these pragmas on, since it seems fine with modern glibc. If that proves problematic too we can rethink or give up the idea, but I think some sort of automatic enforcement of this would be better than relying on reviewers spotting attempts to introduce direct calls to these functions. Disabling for now definitely makes sense. I'll take a look. |
It seems too brittle to enable by default as we'd have to avoid including any system headers after doh.h, which is hard to enforce, but just having it enabled for one CI job should avoid uses of the poisoned symbols from being accidentally introduced. See #2223
Previously code in the SWIG tool didn't handle allocation failures
well. Most places didn't check for NULL return from
malloc()/realloc()/calloc() at all, typically resulting in undefined
behaviour, and some places used assert() to check for a NULL return
(which is a misuse of assert() and such checks disappear if built with
NDEBUG defined leaving us back with undefined behaviour).
All C allocations are now done via wrapper functions (Malloc(),
Realloc() and Calloc()) which emit and error and exit with non-zero
status on failure, so a non-NULL return can be relied upon.
Fixes #1901.