nemequ / munit

µnit is a small testing framework for C
https://nemequ.github.io/munit/
Other
584 stars 76 forks source link

Asserted Macros are Expanded Before Stringification #35

Open webstrand opened 7 years ago

webstrand commented 7 years ago

When most assertion macros are called, they call another macro, and in the process expand the arguments originally passed to the assertion. Since stringification happens in munit_assert_type_full, after the user's macro has been expanded, there's no way to stringify the original expression.

For example:

uint8_t SOME_LONG_UGLY_EXPANSION = 0;
#define FOO SOME_LONG_UGLY_EXPANSION
munit_assert_uint8(FOO, ==, 7);

Will result in the message:

assertion failed: SOME_LONG_UGLY_EXPRESSION == 7 ...

This isn't the behavior I expected. Furthermore if the expansion of the macro contains format-string characters lots of warnings are produced.

I've fixed this in my local copy by adding two additional terms to many internal-use macros through which I pass #a and #b, sometimes adding an additional level of indirection as necessary to preserve the public API.

nemequ commented 7 years ago

Maybe I'm misunderstanding the point of this report, but it seems like µnit already does what you're talking about. You've elided the portion which shows the expanded value. The full string should look something like:

assertion failed: SOME_LONG_UGLY_EXPRESSION == 7 (0 == 7)

Both versions are shown because both can be useful in different situations.

webstrand commented 7 years ago

I guess I should've included the message I expected:

assertion failed: FOO == 7 (0 == 7)

The problem with reporting the expansion of FOO is that a macro's expansion is often cryptic and doesn't provide any additional information. Also if the expansion contains format strings, or even sequences of characters that parse as flags, at best spurious warnings will be produces and at worst the assertion causes a segmentation fault.

If the current behavior is the desired behavior, I suppose the security issues can be fixed by passing the expansion as a parameter to printf rather than using the preprocessor to concatenate the strings.