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

Downcast from Thread to EThread in Thread::Thread is undefined behavior #10966

Closed
kenballus opened this issue Jan 5, 2024 · 1 comment · Fixed by #10976
Closed

Downcast from Thread to EThread in Thread::Thread is undefined behavior #10966

kenballus opened this issue Jan 5, 2024 · 1 comment · Fixed by #10976
Assignees

Comments

@kenballus
Copy link

EThread derives from Thread, but the Thread constructor does a static_cast of this to EThread *:

Thread::Thread()
{
  mutex = new_ProxyMutex();
  MUTEX_TAKE_LOCK(mutex, static_cast<EThread *>(this));
  mutex->nthread_holding += THREAD_MUTEX_THREAD_HOLDING;
}

Dereferencing a pointer cast from Thread * to EThread * is UB when the underlying object was instantiated as a Thread. Since the above cast happens in the Thread constructor, it is UB.

Here's the UBSan error I get during ATS startup that alerted me to this problem:

/app/trafficserver/src/iocore/eventsystem/Thread.cc:42:3: runtime error: downcast of address 0x7fbd81376800 which does not point to an object of type 'EThread'
0x7fbd81376800: note: object is of type 'Thread'
 00 00 00 00  90 89 43 21 3b 56 00 00  00 00 00 00 00 00 00 00  80 8f 00 00 90 62 00 00  00 00 00 00
              ^~~~~~~~~~~~~~~~~~~~~~~
              vptr for 'Thread'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /app/trafficserver/src/iocore/eventsystem/Thread.cc:42:3 in
@kenballus kenballus changed the title Downcast from Thread to EThread in Thread::Thread is undefined behavior Downcast from Thread to EThread in Thread::Thread is undefined behavior Jan 5, 2024
@ywkaras
Copy link
Contributor

ywkaras commented Jan 8, 2024

Thread::Thread() is a protected member, and is the only constructor. Looking at this:

wkaras ~/REPOS/TS
O$ grep '^ *class.*\WThread' $(findsrc)
./include/iocore/eventsystem/EventProcessor.h:  class ThreadInit : public Continuation
./include/iocore/eventsystem/Processor.h:class Thread;
./include/iocore/eventsystem/Thread.h:  class called EThread, derived from Thread. It is the responsibility of
./include/iocore/eventsystem/Thread.h:class Thread
./include/iocore/eventsystem/EThread.h:class EThread : public Thread
./src/iocore/eventsystem/UnixEventProcessor.cc:class ThreadAffinityInitializer : public Continuation
./src/iocore/eventsystem/UnixEventProcessor.cc:class ThreadInitByFunc : public Continuation
./src/proxy/logging/LogObject.cc:class ThreadLocalLogBufferManager : public Continuation
./tools/benchmark/benchmark_ProxyAllocator.cc:class BThread : public Thread
wkaras ~/REPOS/TS
O$ 

It looks like the issue is only a problem in the proxy allocator benchmark tool. Otherwise, Thread instances only exist as subinstances of EThread. But, still krufy and fragile, best removed.

@ywkaras ywkaras linked a pull request Jan 9, 2024 that will close this issue
@ywkaras ywkaras self-assigned this Jan 9, 2024
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 a pull request may close this issue.

2 participants