swineone
swineone

Reputation: 2824

Valgrind reports "invalid write" at "X bytes below stack pointer"

I'm running some code under Valgrind, compiled with gcc 7.5 targeting an aarch64 (ARM 64 bits) architecture, with optimizations enabled.

I get the following error:

==3580== Invalid write of size 8
==3580==    at 0x38865C: ??? (in ...)
==3580==  Address 0x1ffeffdb70 is on thread 1's stack
==3580==  16 bytes below stack pointer

This is the assembly dump in the vicinity of the offending code:

  388640:       a9bd7bfd        stp     x29, x30, [sp, #-48]!
  388644:       f9000bfc        str     x28, [sp, #16]
  388648:       a9024ff4        stp     x20, x19, [sp, #32]
  38864c:       910003fd        mov     x29, sp
  388650:       d1400bff        sub     sp, sp, #0x2, lsl #12
  388654:       90fff3f4        adrp    x20, 204000 <_IO_stdin_used-0x4f0>
  388658:       3dc2a280        ldr     q0, [x20, #2688]
  38865c:       3c9f0fe0        str     q0, [sp, #-16]!

I'm trying to ascertain whether this is a possible bug in my code (note that I've thoroughly reviewed my code and I'm fairly confident it's correct), or whether Valgrind will blindly report any writes below the stack pointer as an error.

Assuming the latter, it looks like a Valgrind bug since the offending instruction at 0x38865c uses the pre-decrement addressing mode, so it's not actually writing below the stack pointer.

Furthermore, at address 0x388640 a similar access (and again with pre-decrement addressing mode) is performed, yet this isn't reported by Valgrind; the main difference being the use of an x register at address 0x388640 versus a q register at address 38865c.

I'd also like to draw attention to the large stack pointer subtraction at 0x388650, which may or may not have anything to do with the issue (note this subtraction makes sense, given that the offending C code declares a large array on the stack).

So, will anyone help me make sense of this, and whether I should worry about my code?

Upvotes: 3

Views: 1307

Answers (3)

Seirios
Seirios

Reputation: 109

Beyond OP issue that was due to a Valgrind bug, the title of this question is bound to attract more people (like me) who are getting "invalid write at X bytes below stack pointer" as a legitimate error.

My piece of advice: check that the address you're writing to is not a local variable of another function (not present in the call stack)!

I stumbled upon this issue while attempting to write into the address returned by yyget_lloc(yyscanner) while outside of function yyparse (the former returns the address of a local variable in the latter).

Upvotes: 0

Nate Eldredge
Nate Eldredge

Reputation: 58558

The code looks fine, and the write is certainly not below the stack pointer. The message seems to be a valgrind bug, possibly #432552, which is marked as fixed. OP confirms that the message is not produced after upgrading valgrind to 3.17.0.

Upvotes: 1

Jeff Holt
Jeff Holt

Reputation: 3190

code declares a large array on the stack

should [I] worry about my code?

I think it depends upon your desire for your code to be more portable.

Take this bit of code that I believe represents at least one important thing you mentioned in your post:

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

long long foo (long long sz, long long v) {
    long long arr[sz]; // allocating a variable on the stack
    arr[sz-1] = v;
    return arr[sz-1];
}

int main (int argc, char *argv[]) {
    long long n = atoll(argv[1]);
    long long v = foo(n, n);
    printf("v = %lld\n", v);
}

$ uname -mprsv
Darwin 20.5.0 Darwin Kernel Version 20.5.0: Sat May  8 05:10:33 PDT 2021; root:xnu-7195.121.3~9/RELEASE_X86_64 x86_64 i386
$ gcc test.c
$ a.out 1047934
v = 1047934
$ a.out 1047935
Segmentation fault: 11

$ uname -snrvmp
Linux localhost.localdomain 3.19.8-100.fc20.x86_64 #1 SMP Tue May 12 17:08:50 UTC 2015 x86_64 x86_64
$ gcc test.c
$ ./a.out 2147483647
v = 2147483647
$ ./a.out 2147483648
v = 2147483648

There are at least some minor portability concerns with this code. The amount of allocatable stack memory for these two environments differs significantly. And that's only for two platforms. Haven't tried it on my Windows 10 vm but I don't think I need to because I got bit by this one a long time ago.

Upvotes: 1

Related Questions