https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69482

            Bug ID: 69482
           Summary: Writing through pointers to volatile not always
                    preserved
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: major
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: wipedout at yandex dot ru
  Target Milestone: ---

I'm trying this on http://gcc.godbolt.org/ The compiler selected is "x86 gcc
5.3.0", the command line option string is "-x c -std=c99 -O3"

This is the code (note pointer to volatile):

#include <stddef.h>

static void memset_s(void* s, size_t n) {
  volatile unsigned char * p = s;
  for(size_t i = 0; i < n; ++i) {
    p[i] = 0;
  }
}

void test() {
  unsigned char x[4];
  memset_s(x, sizeof x);
}

This is the emitted assembly:

test:
        rep ret

Same happens when size of array is 1 and 2. With all other array sizes writes
are preserved. For example, this is emitted for array of size 3:

test:
        movb    $0, -24(%rsp)
        movb    $0, -23(%rsp)
        movb    $0, -22(%rsp)
        ret

and this is emitted for array of size 5:

test:
        movb    $0, -24(%rsp)
        movb    $0, -23(%rsp)
        movb    $0, -22(%rsp)
        movb    $0, -21(%rsp)
        movb    $0, -20(%rsp)
        ret

This is not reproduced in "x86 gcc 4.5.3" but is reproduced in "x86 gcc 4.6.4"
and later. This isn't reproduced in clang.

"secure memset" implementation as above is widely used to overwrite memory
previously used to store encryption keys, passwords and the like. Cases with
size hardcoded and being 1, 2 or 4 look dumb but I have no idea what exactly
causes this unexpected code emission and how serious the real impact is.

Reply via email to