Runtime Sanitizer Issues: Uninitialized structs in tests, and stack buffer read overflow #298
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Issue #, if available: None
Description of changes:
This PR is part of efforts to eliminate the runtime sanitizer errors reported when running in debug mode. Most of the issues were either related to uninitialized data in tests, or non-breaking issues with how the decNumber library is implemented. Specifically, this PR addresses uninitialized test data, and an off-by-one error in a loop that resulted in memory reads from beyond the boundaries of a buffer.
The memory access issue is identified by Clang's AddressSanitizer like so:
The original code consisted of a for loop that:
memcpy
s every 32bit span into a 32bit int before checking to make sure the value is zero and stops if not.Because the boundary check is done after the memcpy, the memcpy ends up reaching beyond the size of the buffer. The data copied is only used as another stopping condition for the loop, and does not corrupt the digit data. It does however trigger the AddressSanitizer during debug build execution and could potentially cause issue with other dynamic analysis tools.
The change in this PR simply swaps the order of the bounds check and memcpy so the evaluation short circuits when memcpy would reach beyond the buffer. The already existing for-loop immediately after the change handles finishing the remainder of the pointer increments to account for non-multiple of 4 buffer sizes, in the same way it did pre-PR.
With this PR, the AddressSanitizer is no longer triggered:
and unit tests still pass as expected:
The uninitialized options in tests triggered the UndefinedBehavior sanitizer, which presented with these:
These were being triggered by two uninitialized structs, but I've added initialization for all structs that were not already initialized at declaration, or memset prior to use since it is pretty dependent on what is in memory at the time of the test.
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.