Bug 1655642 - valgrind wcsncmp reports "Conditional jump or move depends on uninitialised value" on glibc strcmp-avx2.S:113
Summary: valgrind wcsncmp reports "Conditional jump or move depends on uninitialised v...
Keywords:
Status: CLOSED CURRENTRELEASE
Alias: None
Product: Red Hat Enterprise Linux 8
Classification: Red Hat
Component: valgrind
Version: 8.0
Hardware: x86_64
OS: Linux
unspecified
medium
Target Milestone: rc
: 8.0
Assignee: Mark Wielaard
QA Contact: Alexandra Petlanová Hájková
URL:
Whiteboard:
Depends On: 1645971
Blocks:
TreeView+ depends on / blocked
 
Reported: 2018-12-03 15:40 UTC by Mark Wielaard
Modified: 2019-06-14 01:34 UTC (History)
3 users (show)

Fixed In Version: valgrind-3.14.0-5.el8
Doc Type: If docs needed, set a value
Doc Text:
Clone Of: 1645971
Environment:
Last Closed: 2019-06-14 01:34:04 UTC
Type: Bug
Target Upstream Version:


Attachments (Terms of Use)


Links
System ID Priority Status Summary Last Updated
KDE Software Compilation 401627 None None None 2018-12-03 15:40:04 UTC

Description Mark Wielaard 2018-12-03 15:40:04 UTC
+++ This bug was initially created as a clone of Bug #1645971 +++

Description of problem:

Valgrind is reporting what I suspect is a false positive:

"Conditional jump or move depends on uninitialised value" on
glibc strcmp-avx2.S:113

I've created a test program attached that generates the report using wcsncmp.  It appears to be length dependant on the underlying memory that is allocated.
This did not appear in versions of Fedora prior to 29.

The output of the test program is below.

[root@localhost net]# gcc test.c
[root@localhost net]# valgrind ./a.out
==26675== Memcheck, a memory error detector
==26675== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==26675== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==26675== Command: ./a.out
==26675== 


first test case (8 wchar_t), no complaints from valgrind
test case 1 match


second test case (6 wchar_t), valgrind complains
==26675== Conditional jump or move depends on uninitialised value(s)
==26675==    at 0x49C4E59: __wcsncmp_avx2 (strcmp-avx2.S:113)
==26675==    by 0x40121B: main (in /home/russell/net/a.out)
==26675== 
test case 2 match
==26675== 
==26675== HEAP SUMMARY:
==26675==     in use at exit: 0 bytes in 0 blocks
==26675==   total heap usage: 3 allocs, 3 frees, 1,080 bytes allocated
==26675== 
==26675== All heap blocks were freed -- no leaks are possible
==26675== 
==26675== For counts of detected and suppressed errors, rerun with: -v
==26675== Use --track-origins=yes to see where uninitialised values come from
==26675== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)


Version-Release number of selected component (if applicable):

valgrind-3.14.0-1.fc29.x86_64

--- Additional comment from Mark Wielaard on 2018-11-05 07:59:00 EST ---

This probably comes from the following glibc commit glibc-2.27.9000-436-g1457016:

commit 1457016337072d1b6739f571846b619596990cb7
Author: Leonardo Sandoval <leonardo.sandoval.gonzalez@linux.intel.com>
Date:   Thu May 3 11:09:30 2018 -0500

    x86-64: Optimize strcmp/wcscmp and strncmp/wcsncmp with AVX2

strcmp, ecscmp and strncmp have overrides in valgrind shared/vg_replace_strmem.c.
But wcsncmp doesn't.

Comment 1 Mark Wielaard 2018-12-03 15:54:08 UTC
This has an easy reproducer on any x86_64 with avx2 setup. Any program using wcsncmp will produce the issue. The upstream fix contains this test program:

$ cat memcheck/tests/wcs.c 
// Uses various wchar_t * functions that have hand written SSE assembly
// implementations in glibc. wcslen, wcscpy, wcscmp, wcsrchr, wcschr.

#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>

int main(int argc, char **argv)
{
  wchar_t a[] = L"The spazzy orange tiger jumped over the tawny jaguar.";
  wchar_t *b, *c;
  wchar_t *d, *e;

  size_t l = wcslen (a);
  fprintf (stderr, "wcslen: %zd\n", l); // wcslen: 53

  b = (wchar_t *) malloc((l + 1) * sizeof (wchar_t));
  c = wcscpy (b, a);

  fprintf (stderr, "wcscmp equal: %d\n", wcscmp (a, b)); // wcscmp equal: 0

  d = wcsrchr (a, L'd');
  e = wcschr (a, L'd');

  fprintf (stderr, "wcsrchr == wcschr: %d\n", d == e); // wcsrchr == wcschr: 1

  free (c); // b == c
  return 0;
}

$ cp valgrind/memcheck/tests/wcs.c  .
$ gcc -g -o wcs wcs.c 
$ valgrind -q ./wcs 
wcslen: 53
wcscmp equal: 0
==10843== Invalid read of size 32
==10843==    at 0x4F9CD43: __wcsncmp_avx2 (in /usr/lib64/libc-2.28.so)
==10843==    by 0x400A33: main (wcs.c:22)
==10843==  Address 0x5201120 is 8 bytes after a block of size 216 alloc'd
==10843==    at 0x4C30E4B: malloc (vg_replace_malloc.c:299)
==10843==    by 0x4009CA: main (wcs.c:18)
==10843== 
==10843== Invalid read of size 32
==10843==    at 0x4F9CD61: __wcsncmp_avx2 (in /usr/lib64/libc-2.28.so)
==10843==    by 0x400A33: main (wcs.c:22)
==10843==  Address 0x5201140 is 32 bytes before an unallocated block of size 4,193,920 in arena "client"
==10843== 
==10843== Invalid read of size 32
==10843==    at 0x4F9CD66: __wcsncmp_avx2 (in /usr/lib64/libc-2.28.so)
==10843==    by 0x400A33: main (wcs.c:22)
==10843==  Address 0x5201160 is 0 bytes inside an unallocated block of size 4,193,920 in arena "client"
==10843== 
==10843== Conditional jump or move depends on uninitialised value(s)
==10843==    at 0x4F9CD9E: __wcsncmp_avx2 (in /usr/lib64/libc-2.28.so)
==10843==    by 0x400A33: main (wcs.c:22)
==10843== 
wcsncmp equal: 0
wcsrchr == wcschr: 1

With the fix:

$ valgrind -q ./wcs
wcslen: 53
wcscmp equal: 0
wcsncmp equal: 0
wcsrchr == wcschr: 1


Note You need to log in before you can comment on or make changes to this bug.