Skip to content

Fix GH-9068: Conditional jump or move depends on uninitialised value(s) #10221

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

Closed
wants to merge 1 commit into from

Conversation

nielsdos
Copy link
Member

@nielsdos nielsdos commented Jan 4, 2023

Fixes GH-9068
See GH-9068 for analysis.

This patch preserves the scratch registers of the SysV x86-64 ABI by storing them to the stack and restoring them later. We need to do this to prevent the registers of the caller from being corrupted. The reason these get corrupted is because the compiler is unaware of the Valgrind replacement function and thus makes assumptions about the original function regarding registers which are not true for the replacement function.

I considered the alternative of using target function attributes, but that's not supported on GCC<7.0 and on ICC.

@nielsdos
Copy link
Member Author

nielsdos commented Jan 5, 2023

I pushed a new version that uses inline assembly to define the function and calls a wrapper, which should be more robust because we have full control and the compiler cannot mess with our store and restore procedure.

@nielsdos
Copy link
Member Author

nielsdos commented Jan 6, 2023

This PR might need an adjustment regarding the platforms where this wrapper is applied to. The code is currently guarded by defined(__GNUC__) && defined(__x86_64__) && !defined(__ILP32__) && !defined(__MACH__). One problem case was macOS (denylisted with !defined(__MACH__)) because macOS doesn't support directives like .type and .size. But perhaps there are other platforms with __GNUC__ (e.g. Clang on Windows maybe) that don't support these directives? So the denylist may need to be changed to an allowlist. I'll wait for reviewers to comment on this.

@nielsdos
Copy link
Member Author

nielsdos commented Jan 7, 2023

Thanks for the review. I applied your comments and I also changed the denylist of the platforms to an allowlist.

EDIT: test failure in macOS seems unrelated.

@nielsdos
Copy link
Member Author

nielsdos commented May 2, 2023

I have been bitten by this a couple of times again.
I discarded the old inline assembly approach because it is hacky and not very portable and was quite a long implementation. The new approach is a short implementation.
I instead used the attribute no_caller_saved_registers which works around the issue, in combination with the target pragma (not specifying the target pragma would result in a compile error because no_caller_saved_registers would normally not allow an SSE target).

…ue(s)

This patch preserves the scratch registers of the SysV x86-64 ABI by storing
them to the stack and restoring them later. We need to do this to prevent the
registers of the caller from being corrupted. The reason these get corrupted
is because the compiler is unaware of the Valgrind replacement function and
thus makes assumptions about the original function regarding registers which
are not true for the replacement function.

For implementation I used a GCC and Clang attribute. A more general
approach would be to use inline assembly but that's also less portable
and quite hacky. This attributes is supported since GCC 7.x, but the
target option is only supported since 11.x. For Clang the target option
does not matter.
Copy link
Member

@iluuu1994 iluuu1994 left a comment

Choose a reason for hiding this comment

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

LGTM otherwise, thanks Niels!

{
return !memcmp(ZSTR_VAL(s1), ZSTR_VAL(s2), ZSTR_LEN(s1));
}

#if defined(__GNUC__) && __GNUC__ >= 11 && !defined(__clang__) && __has_attribute(no_caller_saved_registers)
Copy link
Member

Choose a reason for hiding this comment

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

nit: Maybe define a macro after push_options and check for this instead of repeating the condition?

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 this pull request may close these issues.

3 participants