-
Notifications
You must be signed in to change notification settings - Fork 11.8k
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
[asan] False positive ODR violation error for global data (e.g. vtable) #101671
Comments
So I've been thinking more about this error and I understand why on a "physical" level it's correct - after all there are two copies of the symbol definition. On the other hand, from the point of view of the developer, that's not really the case. There is one source file, one compiler invocation, one object file/library, one dependency graph node with the definition. The fact that it gets duplicated at runtime is just an implementation detail. As far as I understand, the POSIX runtime linking model (assuming correct visibility handling) specifically makes it so that shared libraries act a lot like static libraries, in the sense that there is only one "active" copy of each symbol at runtime, and those symbols' addresses compare equal from different libraries. This means that after runtime symbol resolution there is actually only one definition (from the abstract machine's point of view), as the other definition is not observable. This is exactly why Boost.Filesystem marks its Now if the symbols came from different compiler invocations then this would clearly be an ODR violation. That being said, it seems odd that GCC and Clang have different behaviors in the case of vtables. This is a case which must come up a lot in real codebases, especially for exception types. |
I would assume that your linkage of a |
This is definitely the case, and it's probably (strictly speaking) the correct behavior from the point of view of the standard. On the other hand, the standard doesn't really acknowledge the existence of shared libraries. And so from this point of view the more "useful" behavior might be to check provenance of the symbols (some kind of TU compilation UUID maybe?). A separate issue is that specifically for vtables, GCC and Clang disagree on their weakness/strength, and as a result on sanitizer instrumentation. All in all, I totally understand if this is deemed to be not-a-bug. |
Hi!
This issue initially manifested itself as an ODR violation for
vtable for boost::filesystem::filesystem_error
when Boost.Filesystem is a static library linked into two shared libraries (built with Clang).After some minimization it appears to be an issue common to all global non-weak data (symbol types
D
andB
innm
's output). On Clang this affects vtables while on GCC it does not because its vtables are weak symbols (or maybe they just aren't checked since they don't have associated__odr_asan.
symbols?).Here's the setup which reproduces the issue on both Clang and GCC:
fs
includes anextern int global_var
.lib
usesglobal_var
fromfs
somehow to avoid it being discarded.exe
usesglobal_var
fromfs
somehow to avoid it being discarded, and also links tolib
.When running the executable we get the error:
I've minimized the flags required and really the only one is
-fsanitize=address
:cpp_flags=(-fPIC -O0 -fsanitize=address) link_flags=("-Wl,-rpath,\$ORIGIN")
-fvisibility=hidden
doesn't affect anything as long as the symbols of interest are marked[[gnu::visibility("default")]]
.I'm attaching a zip file with a full example: asan-odr-repro.zip
Tested on Linux x86_64.
Clang 16.0.6, 18.1.8 and
main
all exhibit the same behavior including for vtables.GCC 11.4 and 12.3 only exhibit the behavior for global variables.
The text was updated successfully, but these errors were encountered: