Bug 489707

Summary: Conditional jump or move depends on uninitialised value(s)" shouldn't apply to assertions.
Product: [Developer tools] valgrind Reporter: Daniel Black <daniel>
Component: memcheckAssignee: Julian Seward <jseward>
Status: RESOLVED NOT A BUG    
Severity: normal CC: pjfloyd
Priority: NOR    
Version: 3.23.0   
Target Milestone: ---   
Platform: Other   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:

Description Daniel Black 2024-07-04 00:42:28 UTC
SUMMARY

Defensive code can use assertions around uninitialised values to protect against undefined behaviour. While valgrind does the same thing, to do both there is now a different compile option to test under valgrind.

STEPS TO REPRODUCE

1. t.c

#include <assert.h>

int main()
{
  unsigned long n;
  char *b = (char *) &n;

  *b = 1;
  assert((n & ~0xFFUL) == 0);

}

2.  gcc -o /tmp/t /tmp/t.c
3. valgrind /tmp/t

OBSERVED RESULT

==1111332== Conditional jump or move depends on uninitialised value(s)
==1111332==    at 0x401147: main (in /tmp/t)

EXPECTED RESULT

no error.

SOFTWARE/OS VERSIONS

Linux (Fedora 40)
(gcc 14.1.1)

ADDITIONAL INFORMATION

This didn't trigger as error on valgrind 3.18.1.

ref: https://jira.mariadb.org/browse/MDEV-34502
and workaround: https://github.com/MariaDB/server/pull/3378
notably: valgrind didn't error on the subsequent statements reading n
Comment 1 Paul Floyd 2024-07-04 08:10:25 UTC
First, are you certain that it was only the change from Valgrind 3.18.1 to Valgrind 3.23 that caused the change?

I just checked out the code for 3.18.1 and using GCC 14.1 on RHEL 7..6 I get the same error with both that version and git HEAD.

Second, there is no way for us to know when an expression is used in an assert. On amd64 your example code produces

  40114a:       c6 00 01                movb   $0x1,(%rax)
  40114d:       48 8b 45 f0             mov    -0x10(%rbp),%rax
  401151:       48 3d ff 00 00 00       cmp    $0xff,%rax
  401157:       76 19                   jbe    401172 <main+0x3c>
  401159:       b9 23 20 40 00          mov    $0x402023,%ecx
  40115e:       ba 09 00 00 00          mov    $0x9,%edx
  401163:       be 04 20 40 00          mov    $0x402004,%esi
  401168:       bf 10 20 40 00          mov    $0x402010,%edi
  40116d:       e8 be fe ff ff          call   401030 <__assert_fail@plt>
  401172:       b8 00 00 00 00          mov    $0x0,%eax
  401177:       c9                      leave
  401178:       c3                      ret

where the opcodes
  401151:       48 3d ff 00 00 00       cmp    $0xff,%rax
  401157:       76 19                   jbe    401172 <main+0x3c>
are triggering the error. At the moment of the error we can't tell that the false case leads to a call to __assert_fail.

Thirdly, and this is the really fundamental problem, you don't seem to understand the nature of Undefined Behaviour.

There are two possibilities. Either your program text is well-formed or it is ill-formed. If it is well-formed then you can reason about it. You can say things like "if A is true then B should happen". If it is ill-formed then that is it. You cannot reason about ill-formed code.

See
https://en.cppreference.com/w/c/language/behavior
and
https://youtu.be/yG1OZ69H_-o?feature=shared

So, in summary
1. this would be difficult to impllement
2. I think that it would be a serious mistake for us to do anything that masks UB.
Comment 2 Daniel Black 2024-07-04 09:08:47 UTC
Might have been a compiler change.

Agree with other statements.

Thanks for your time.