MINOR: compiler: add a new macro ALREADY_CHECKED()
This macro may be used to block constant propagation that lets the compiler detect a possible NULL dereference on a variable resulting from an explicit assignment in an impossible check. Sometimes a function is called which does safety checks and returns NULL if safe conditions are not met. The place where it's called cannot hit this condition and dereferencing the pointer without first checking it will make the compiler emit a warning about a "potential null pointer dereference" which is hard to work around. This macro "washes" the pointer and prevents the compiler from emitting tests branching to undefined instructions. It may only be used when the developer is absolutely certain that the conditions are guaranteed and that the pointer passed in argument cannot be NULL by design. A typical use case is a top-level function doing this : if (frame->type == HEADERS) parse_frame(frame); Then parse_frame() does this : void parse_frame(struct frame *frame) { const char *frame_hdr; frame_hdr = frame_hdr_start(frame); if (*frame_hdr == FRAME_HDR_BEGIN) process_frame(frame); } and : const char *frame_hdr_start(const struct frame *frame) { if (frame->type == HEADERS) return frame->data; else return NULL; } Above parse_frame() is only called for frame->type == HEADERS so it will never get a NULL in return from frame_hdr_start(). Thus it's always safe to dereference *frame_hdr since the check was already performed above. It's then safe to address it this way instead of inventing dummy error code paths that may create real bugs : void parse_frame(struct frame *frame) { const char *frame_hdr; frame_hdr = frame_hdr_start(frame); ALREADY_CHECKED(frame_hdr); if (*frame_hdr == FRAME_HDR_BEGIN) process_frame(frame); }
This commit is contained in:
parent
50d660c545
commit
071d4b31ff
|
@ -94,6 +94,20 @@
|
||||||
#define my_unreachable()
|
#define my_unreachable()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* This macro may be used to block constant propagation that lets the compiler
|
||||||
|
* detect a possible NULL dereference on a variable resulting from an explicit
|
||||||
|
* assignment in an impossible check. Sometimes a function is called which does
|
||||||
|
* safety checks and returns NULL if safe conditions are not met. The place
|
||||||
|
* where it's called cannot hit this condition and dereferencing the pointer
|
||||||
|
* without first checking it will make the compiler emit a warning about a
|
||||||
|
* "potential null pointer dereference" which is hard to work around. This
|
||||||
|
* macro "washes" the pointer and prevents the compiler from emitting tests
|
||||||
|
* branching to undefined instructions. It may only be used when the developer
|
||||||
|
* is absolutely certain that the conditions are guaranteed and that the
|
||||||
|
* pointer passed in argument cannot be NULL by design.
|
||||||
|
*/
|
||||||
|
#define ALREADY_CHECKED(p) do { asm("" : "=rm"(p) : "0"(p)); } while (0)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Gcc >= 3 provides the ability for the programme to give hints to the
|
* Gcc >= 3 provides the ability for the programme to give hints to the
|
||||||
* compiler about what branch of an if is most likely to be taken. This
|
* compiler about what branch of an if is most likely to be taken. This
|
||||||
|
|
Loading…
Reference in New Issue