SUMMARY Invalid read found in __wcsncpy_avx2 (strncpy-avx2.S:308) when running Python software, may need a suppression as it's from glibc. STEPS TO REPRODUCE 1. Run 'valgrind --trace-children=yes emerge -pvO bash' on a Gentoo Linux system 2. I suspect that it's related to a recent change in Gentoo where we allowed glibc's autodetection of x86 ISA for runtime loading OBSERVED RESULT ``` $ valgrind --trace-children=yes emerge -pvO bash ==1273477== Memcheck, a memory error detector ==1273477== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. ==1273477== Using Valgrind-3.21.0 and LibVEX; rerun with -h for copyright info ==1273477== Command: /usr/bin/emerge -pvO bash ==1273477== ==1273477== Memcheck, a memory error detector ==1273477== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. ==1273477== Using Valgrind-3.21.0 and LibVEX; rerun with -h for copyright info ==1273477== Command: /usr/lib/python-exec/python3.12/emerge -pvO bash ==1273477== ==1273477== Invalid read of size 32 ==1273477== at 0x5038C93: __wcsncpy_avx2 (strncpy-avx2.S:308) ==1273477== by 0x4B209F3: UnknownInlinedFun (wchar2.h:81) ==1273477== by 0x4B209F3: _Py_wrealpath (fileutils.c:2130) ==1273477== by 0x4B18540: _PyPathConfig_ComputeSysPath0.constprop.0 (pathconfig.c:495) ==1273477== by 0x4B17D6C: UnknownInlinedFun (main.c:584) ==1273477== by 0x4B17D6C: Py_RunMain (main.c:689) ==1273477== by 0x4AD59FB: Py_BytesMain (main.c:743) ==1273477== by 0x4F05346: (below main) (libc_start_call_main.h:58) ==1273477== Address 0x5581be0 is 20 bytes after a block of size 156 alloc'd ==1273477== at 0x4840958: malloc (vg_replace_malloc.c:431) ==1273477== by 0x4AD7116: decode_current_locale (fileutils.c:482) ==1273477== by 0x4AD5988: Py_DecodeLocale (fileutils.c:664) ==1273477== by 0x4B209CE: _Py_wrealpath (fileutils.c:2119) ==1273477== by 0x4B18540: _PyPathConfig_ComputeSysPath0.constprop.0 (pathconfig.c:495) ==1273477== by 0x4B17D6C: UnknownInlinedFun (main.c:584) ==1273477== by 0x4B17D6C: Py_RunMain (main.c:689) ==1273477== by 0x4AD59FB: Py_BytesMain (main.c:743) ==1273477== by 0x4F05346: (below main) (libc_start_call_main.h:58) ==1273477== --1273477-- WARNING: unhandled amd64-linux syscall: 441 --1273477-- You may be able to write your own handler. --1273477-- Read the file README_MISSING_SYSCALL_OR_IOCTL. --1273477-- Nevertheless we consider this a bug. Please report --1273477-- it at http://valgrind.org/support/bug_reports.html. ^C ``` EXPECTED RESULT No invalid reads. SOFTWARE/OS VERSIONS Reproduced on Valgrind 3.21.0 and git master as of a few days ago. ADDITIONAL INFORMATION I'm going to try get a reproducer that doesn't involve a large Python program but no promises.
Python source here: https://github.com/python/cpython/blob/84b7e9e3fa67fb9b92088d17839d8235f1cec62e/Python/fileutils.c#L2104
And https://en.cppreference.com/w/c/string/wide/wcsncpy
Finally https://elixir.bootlin.com/glibc/glibc-2.38/source/sysdeps/x86_64/multiarch/strncpy-avx2.S
Minimal reproducer: #include <string.h> #include <wchar.h> #include <stdlib.h> int main () { wchar_t *bar = calloc(121, sizeof (wchar_t)); wmemset (bar, 1, 120); wchar_t *foo = calloc(256, sizeof (wchar_t)); wcsncpy (foo, bar, 255); } ~$ gcc -O3 ~/test.c && valgrind ./a.out ==4093631== Memcheck, a memory error detector ==4093631== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. ==4093631== Using Valgrind-3.21.0 and LibVEX; rerun with -h for copyright info ==4093631== Command: ./a.out ==4093631== ==4093631== Invalid read of size 32 ==4093631== at 0x49ECE2D: __wcsncpy_avx2 (strncpy-avx2.S:337) ==4093631== by 0x1090B3: main (in /home/arsen/a.out) ==4093631== Address 0x4a72240 is 16 bytes after a block of size 496 in arena "client" ==4093631== ==4093631== Conditional jump or move depends on uninitialised value(s) ==4093631== at 0x49ECE51: __wcsncpy_avx2 (strncpy-avx2.S:348) ==4093631== by 0x1090B3: main (in /home/arsen/a.out) ==4093631== ==4093631== ==4093631== HEAP SUMMARY: ==4093631== in use at exit: 1,508 bytes in 2 blocks ==4093631== total heap usage: 2 allocs, 0 frees, 1,508 bytes allocated ==4093631== ==4093631== LEAK SUMMARY: ==4093631== definitely lost: 1,508 bytes in 2 blocks ==4093631== indirectly lost: 0 bytes in 0 blocks ==4093631== possibly lost: 0 bytes in 0 blocks ==4093631== still reachable: 0 bytes in 0 blocks ==4093631== suppressed: 0 bytes in 0 blocks ==4093631== Rerun with --leak-check=full to see details of leaked memory ==4093631== ==4093631== Use --track-origins=yes to see where uninitialised values come from ==4093631== For lists of detected and suppressed errors, rerun with: -s ==4093631== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) ~$
Note we already have a wcscpy test in memcheck/tests/wcs.c And a replacement function in shared/vg_replace_strmem.c The simplest fix would be to extend that wcscpy test/replacement to wcsncpy.
Created attachment 162341 [details] Modified srmem functions file Haven't had time to test this yet. I'll try to write some tests tonight.
LGTM ~/.../_build/_pfx/bin$ gcc -O3 ~/test.c && valgrind ./a.out ==3321707== Memcheck, a memory error detector ==3321707== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. ==3321707== Using Valgrind-3.21.0 and LibVEX; rerun with -h for copyright info ==3321707== Command: ./a.out ==3321707== ==3321707== Invalid read of size 32 ==3321707== at 0x49ECE2D: __wcsncpy_avx2 (strncpy-avx2.S:337) ==3321707== by 0x1090B3: main (in /home/arsen/valgrind/_build/_pfx/bin/a.out) ==3321707== Address 0x4a72240 is 16 bytes after a block of size 496 in arena "client" ==3321707== ==3321707== Conditional jump or move depends on uninitialised value(s) ==3321707== at 0x49ECE51: __wcsncpy_avx2 (strncpy-avx2.S:348) ==3321707== by 0x1090B3: main (in /home/arsen/valgrind/_build/_pfx/bin/a.out) ==3321707== ==3321707== ==3321707== HEAP SUMMARY: ==3321707== in use at exit: 1,508 bytes in 2 blocks ==3321707== total heap usage: 2 allocs, 0 frees, 1,508 bytes allocated ==3321707== ==3321707== LEAK SUMMARY: ==3321707== definitely lost: 1,508 bytes in 2 blocks ==3321707== indirectly lost: 0 bytes in 0 blocks ==3321707== possibly lost: 0 bytes in 0 blocks ==3321707== still reachable: 0 bytes in 0 blocks ==3321707== suppressed: 0 bytes in 0 blocks ==3321707== Rerun with --leak-check=full to see details of leaked memory ==3321707== ==3321707== Use --track-origins=yes to see where uninitialised values come from ==3321707== For lists of detected and suppressed errors, rerun with: -s ==3321707== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) ~/.../_build/_pfx/bin$ gcc -O3 ~/test.c && ./valgrind ./a.out ==3321824== Memcheck, a memory error detector ==3321824== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. ==3321824== Using Valgrind-3.22.0.GIT and LibVEX; rerun with -h for copyright info ==3321824== Command: ./a.out ==3321824== ==3321824== ==3321824== HEAP SUMMARY: ==3321824== in use at exit: 1,508 bytes in 2 blocks ==3321824== total heap usage: 2 allocs, 0 frees, 1,508 bytes allocated ==3321824== ==3321824== LEAK SUMMARY: ==3321824== definitely lost: 1,508 bytes in 2 blocks ==3321824== indirectly lost: 0 bytes in 0 blocks ==3321824== possibly lost: 0 bytes in 0 blocks ==3321824== still reachable: 0 bytes in 0 blocks ==3321824== suppressed: 0 bytes in 0 blocks ==3321824== Rerun with --leak-check=full to see details of leaked memory ==3321824== ==3321824== For lists of detected and suppressed errors, rerun with: -s ==3321824== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) ~/.../_build/_pfx/bin$
Fixed with https://sourceware.org/git/?p=valgrind.git;a=commit;h=f7829b6d4783f94fce6ea3323fb13d21ff025913 for 3.22
(In reply to Sam James from comment #8) > Fixed with > https://sourceware.org/git/?p=valgrind.git;a=commit; > h=f7829b6d4783f94fce6ea3323fb13d21ff025913 for 3.22 (thank you everyone)