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

Address issues reported by Undefined Behavior Sanitizer running IlmImfTest #828

Merged

Conversation

peterhillman
Copy link
Contributor

Running IlmImfTest when compiling with clang's UndefinedBehaviorSanitizer (UBSan) reported various issues, which are addressed here.

IlmThread

The only way to join an IlmThread (i.e. wait for it to finish) is to delete it, as there's a join() in the base class destructor. However, that means a thread derived from IlmThread will have its destructor called while it is running. The thread object's vtable will change underneath it, making it impossible to call virtual functions. I think it might also lead to a use-after-free issue, as the derived class destructor will be called while it is running.
This change adds a join() to the Thread function. The ThreadPool uses this to ensure worker threads have terminated before deleting them. Code directly using Thread should call Thread::join() before the object is deleted (or goes out of scope). Thread::join is not virtual, so the ABI is backwards compatible

Pointer overflow

The Slice mechanism in FrameBuffer can require 'negative pointers' for the base item when the image bbox is cropped, as it points to the coordinates of pixel (0,0) which may be outside the image data. Performing arithmetic on a pointer that results in negative values is undefined behavior. This change uses intptr_t for such math instead of char* which sneakily suppresses the warning.

Pointer alignment

4 byte ints and floats can only be read/written from 4-byte aligned addresses, and 8 byte ints from 8-byte aligned addresses. A partial fix supported float access, for 32 bit ARM processors. This extends the fix to all types.

minor bugfixes

UBSan also spotted a few issues in the test suite: a division by zero, indexing into unintialized Array2Ds, and an iterator that didn't iterate

Signed-off-by: Peter Hillman <peterh@wetafx.co.nz>
…r undefined)

Signed-off-by: Peter Hillman <peterh@wetafx.co.nz>
Signed-off-by: Peter Hillman <peterh@wetafx.co.nz>
Signed-off-by: Peter Hillman <peterh@wetafx.co.nz>
Copy link
Contributor

@meshula meshula left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice

@@ -99,12 +103,18 @@ bool compare(const FrameBuffer& asRead,
exit(1);
}


//
// extract value written to gile
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"file", not "gile"?

@@ -150,7 +150,7 @@ readWriteFiles (const char fileName1[],
file2.setFrameBuffer (pixels2 - dx - dy * w, 1, w);
file2.readPixels (dw.min.y, dw.max.y);

for (int i = 0; i < w * h; ++h)
for (size_t i = 0; i < w * h; ++i)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow.


// cast to half float if necessary
if(it.slice().type==OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT)
{
* (float *)(it.slice().base + y*it.slice().yStride + x*it.slice().xStride) = value;

* reinterpret_cast<float*>(base + y*it.slice().yStride + x*it.slice().xStride) = value;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These statements sure would be easier to read split in two, with a pointer variable assignment followed by the *ptr = value:

float* ptr = reinterpret_cast<float*>(base + y*it.slice().yStride + x*it.slice().xStride);
*ptr = value;

@cary-ilm cary-ilm merged commit 3c05eac into AcademySoftwareFoundation:master Sep 7, 2020
@peterhillman peterhillman deleted the ubsan_ilmimftest_fixes branch September 7, 2020 22:05
@Jamaika1
Copy link

#837 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants