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

darray.h: avoid UB when decrementing zero pointer #81

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Hi-Angel
Copy link

This PR is a backport of this one.

Sometimes the &(arr).item[(arr).size] is a zero pointer. In these
cases decrementing this pointer aka i results in something like
0xfffffff8. This is UB, and UB sanitizer in particular reports it as

../iscsi/tcmu-runner/libtcmu.c:563:2: runtime error: pointer index expression with base 0x000000000000 overflowed to 0xfffffffffffffff8

In these cases size is zero as well, so fix this by simply not running
the cycle when the size is zero.

Signed-off-by: Konstantin Kharlamov [email protected]

@dgibson
Copy link
Collaborator

dgibson commented Jul 28, 2019

Ugh, this is a bit of a problem. The bug is real, and the patch does address it, but it's not actualy macro safe. If you had this code:

if (something)
    darray_foreach_reverse(...)
        ...
else
     something_else()

The else would get attached to the if in the macro which is almost certainly not what you wanted.

The usual trick of a do {} while wrapper obviously won't work here for a foreach() style macro. I think we have to try to fold the external condition into the loop condition instead.

@Hi-Angel
Copy link
Author

Good note. I'm thinking something like this can do it:

#define darray_foreach_reverse(ptr, arr)           \
    for (size_t i = 0; i < (arr).size; (ptr) = &(arr).item[(arr).size - i], i++)

except this code doesn't do assignment to ptr on the first cycle. I think there was some hack to do assignment in part of for-loop where comparison happens, i.e. for(…; HERE;…), will try to figure it out a bit later (suggestions are welcome though :)).

@Hi-Angel
Copy link
Author

Okay, done. Turns out, assignment in C returns the assigned value, so I used that trick to make it work.

Pushed, please see if you're okay with it.

Sometimes the `&(arr).item[(arr).size]` is a zero pointer. In these
cases decrementing this pointer aka `i` results in something like
0xfffffff8. This is UB, and UB sanitizer in particular reports it as

../iscsi/tcmu-runner/libtcmu.c:563:2: runtime error: pointer index expression with base 0x000000000000 overflowed to 0xfffffffffffffff8

In these cases size is `zero` as well, so fix this by simply not running
the cycle when the `size` is zero.

Signed-off-by: Konstantin Kharlamov <[email protected]>
@Hi-Angel
Copy link
Author

Small update: I figured the assignment is a waste when comparison fails, so I swapped left and right parts of the …&&… expression in the loop.

@Hi-Angel
Copy link
Author

ping

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.

2 participants