-
Notifications
You must be signed in to change notification settings - Fork 6
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
Fix multiple buffer overflows and a buffer underflow. #78
Conversation
…uld happen with the exception of echo, which truncates instead. Fixed underflow in utils/uart.cpp strip().
…les/core.cpp, removed debug printout in string_utils.cpp.
I want to add, for clarity, that the return of sprintf, snprintf and vsnprintf says how much would have been written to the buffer (in case of sprintf the actual amount written). The echo() overflow was caused by this behavior, as the pos value added by vsnprintf to pos could exceed the length of the buffer (whilst not actually writing past the buffer). The issue arises when adding the newline char in the following sprintf call, where the offset then could exceed the buffer size. |
There is one more potential issue (which might warrant its own issue/pr). When the function Serial::read_line is called and there are more than 2 lines in the uart buffer, the pattern positions returned by uart_pattern_get_pos and uart_pattern_pop_pos for the second pattern position can be incorrect, when the buffer is read in 2 different read_line calls. As far as I could see, the pattern positions never get updated when calling uart_read_bytes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for yet another valuable pull request, @SeaTechRC!
After reviewing your changes, I've just got a few thoughts:
-
I simplified the truncation in
echo()
a bit, becausepos
was 0 and could be omitted, so that the newpos
is basically the minimum ofnum_chars
and the buffer size. I think usingstd::min
reflects the intention of this code more clearly. -
Can you elaborate a bit on the new
if (pos >= buffer_len) { }
block inSerial::read_line
? There's quite a lot going on and it's not completely obvious to me how it works. -
Currently you call buffer-related functions like this:
write(buffer, sizeof(buffer), ...) write(&buffer[pos], sizeof(buffer) - pos, ...)
I wonder if it would be more intuitive to change it to
write(buffer, 0, ...) write(buffer, pos, ...)
i.e. passing buffer and start position rather than buffer and size. This would remove boilerplate code from the callees into the function, which can determine the size itself using
sizeof(buffer)
. What do you think?
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Ok, I changed the upper limit to
sizeof(buffer) - 2
. - I guess this makes sense.
- Good point! I wasn't aware of this limitation.
@JensOgorek I've reviewed this PR and it looks good to me. Feel free to merge it whenever you're ready.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was almost done, but waited since you were changing some stuff.
Looks good to me as well.
Hello,
Upon investigation there are multiple places where buffer-overflows could occur aswell as one case of a potential underflow in strip().
The solution i propose is: instead of using sprintf directly without checking the if the buffer overflows or using nsprintf and adding a bunch of code for checking the return value, add csprintf (checked sprintf) which throws an exception in case the buffer is too small.
This change requires some changes in function signatures to propogate the size of the buffer used (notably in the Serial module).
The echo function is a special case which should never fail (since the device running lizard could become "mute"). Therefore the output will get truncated if the buffer overflows.
Ideally, the echo function should not truncate either. This would require the use of vprintf.
The drawback would be the potential of blocking the main thread in case the output buffer of the uart driver is full (the potential is already there if the uart driver buffer has not been cleared until the next echo()).
Kind regards