The AVX2 enumeration for 'wc -l' is incomplete which may cause wc to crash.
The Intel SDM documents the whole AVX2 enumeration sequence in its "Detection of Intel AVX2" section. There are three pieces: 1. Ensuring the CPU supports AVX2 instructions 2. Ensuring the OS has enabled XSAVE 3. Ensuring XSAVE is managing the YMM registers (XGETBV) The existing code does #1 and #2 but misses #3. The kernel will enable #3 in almost all situations where AVX2 is supported, but there are situations where the kernel might disable XSAVE YMM support but leave FP and SSE enabled. This is _unusual_ today, but can occur when Linux notices XSAVE enumeration issues or in virtual machines with odd/buggy XSAVE enumeration. If wc is used on one of those systems in '-l' mode, it will crash: # cat foo | ./wc.orig -l Illegal instruction (core dumped) Fortunately, gcc and llvm provide a builtin to check for CPU support and AVX2 is supported. Use the builtin instead of using CPUID directly. This fixes the problem and is also substantially simpler. The result is that wc no longer crashes on systems where XSAVE YMM support is disabled: # cat foo | ./wc.fixed -l 30232 I've reproduced this issue in the current upstream git repo which git describe says is v9.3-53-g378902407. I needed to run a patched version of Linux to expose this issue. We (the upstream Linux x86 maintainers) are considering merging a patch to do this in the upstream kernel. It would be great if a wc fix was available. --- src/wc.c | 36 +----------------------------------- 1 file changed, 1 insertion(+), 35 deletions(-) diff --git a/src/wc.c b/src/wc.c index becceda98..944cfc426 100644 --- a/src/wc.c +++ b/src/wc.c @@ -157,41 +157,7 @@ static enum total_type total_mode = total_auto; static bool avx2_supported (void) { - unsigned int eax = 0; - unsigned int ebx = 0; - unsigned int ecx = 0; - unsigned int edx = 0; - bool getcpuid_ok = false; - bool avx_enabled = false; - - if (__get_cpuid (1, &eax, &ebx, &ecx, &edx)) - { - getcpuid_ok = true; - if (ecx & bit_OSXSAVE) - avx_enabled = true; /* Support is not disabled. */ - } - - - if (avx_enabled) - { - eax = ebx = ecx = edx = 0; - if (! __get_cpuid_count (7, 0, &eax, &ebx, &ecx, &edx)) - getcpuid_ok = false; - else - { - if (! (ebx & bit_AVX2)) - avx_enabled = false; /* Hardware doesn't support it. */ - } - } - - - if (! getcpuid_ok) - { - if (debug) - error (0, 0, "%s", _("failed to get cpuid")); - return false; - } - else if (! avx_enabled) + if (!__builtin_cpu_supports("avx2")) { if (debug) error (0, 0, "%s", _("avx2 support not detected")); -- 2.34.1