]> git.ipfire.org Git - thirdparty/haproxy.git/commit
MINOR: compiler: add a new macro ALREADY_CHECKED()
authorWilly Tarreau <w@1wt.eu>
Sat, 8 Dec 2018 14:20:43 +0000 (15:20 +0100)
committerWilly Tarreau <w@1wt.eu>
Sat, 8 Dec 2018 14:27:03 +0000 (15:27 +0100)
commit071d4b31ff25e0c665e996080248af542b50f843
tree8ddcdba96c837bdf423acfecd94e1d45b8337a25
parent50d660c54599db6ef05b267ac1e062d3718b035f
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);
    }
include/common/compiler.h