Thread
-
Spurious warnings in crypto-des.c when building with gcc-16 -O3
Andres Freund <andres@anarazel.de> — 2026-04-29T17:47:08Z
Hi, Recently I got a bit of a shock building postgres with gcc-16: ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c: In function ‘px_crypt_des’: ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:675:22: warning: writing 8 bytes into a region of size 7 [-Wstringop-overflow=] 675 | *q++ = *key << 1; | ~~~~~^~~~~~~~~~~ ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: note: at offset [1, 2] into destination object ‘keybuf’ of size 8 659 | keybuf[2]; | ^~~~~~ ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: note: at offset [2, 3] into destination object ‘keybuf’ of size 8 ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: note: at offset [3, 4] into destination object ‘keybuf’ of size 8 ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: note: at offset [4, 5] into destination object ‘keybuf’ of size 8 ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: note: at offset [5, 6] into destination object ‘keybuf’ of size 8 ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: note: at offset [6, 7] into destination object ‘keybuf’ of size 8 ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: note: at offset [7, 8] into destination object ‘keybuf’ of size 8 ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:675:22: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 675 | *q++ = *key << 1; | ~~~~~^~~~~~~~~~~ ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: note: at offset 8 into destination object ‘keybuf’ of size 8 659 | keybuf[2]; | ^~~~~~ ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: note: at offset [9, 10] into destination object ‘keybuf’ of size 8 ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: note: at offset [10, 11] into destination object ‘keybuf’ of size 8 ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: note: at offset [11, 12] into destination object ‘keybuf’ of size 8 ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: note: at offset [12, 13] into destination object ‘keybuf’ of size 8 ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: note: at offset [13, 14] into destination object ‘keybuf’ of size 8 ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: note: at offset [14, 15] into destination object ‘keybuf’ of size 8 Luckily it turns out that that the warning is spurious, due to a bug in gcc [1]. However, it took me quite a while to figure out what the hell the code was doing: char * px_crypt_des(const char *key, const char *setting) { uint32 keybuf[2]; ... uint8 *q; ... /* * Copy the key, shifting each character up by one bit and padding with * zeros. */ q = (uint8 *) keybuf; while (q - (uint8 *) keybuf - 8) { *q++ = *key << 1; if (*key != '\0') key++; } Like, it's far from immediately obvious where the 8 is coming from (it's the size of keybuf), whether there are precedence issues or what this is even trying to achieve. And it's still not clear to me why on earth it makes sense to write it that complicated, when it seems something like for (int byteno = 0; byteno < sizeof(keybuf); byteno++) { *q++ = *key << 1; if (*key != '\0') key++; } would do the same thing, except be trivially understandable for humans and compilers. Am I missing something or is what I suggest equivalent? Any reason to not change it that way, both to clarify the code and to work around the spurious warning? Greetings, Andres Freund [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113664 -
Re: Spurious warnings in crypto-des.c when building with gcc-16 -O3
Ayush Tiwari <ayushtiwari.slg01@gmail.com> — 2026-04-29T19:13:12Z
Hi, On Wed, 29 Apr 2026 at 23:17, Andres Freund <andres@anarazel.de> wrote: > Hi, > > Recently I got a bit of a shock building postgres with gcc-16: > > ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c: In > function ‘px_crypt_des’: > ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:675:22: > warning: writing 8 bytes into a region of size 7 [-Wstringop-overflow=] > 675 | *q++ = *key << 1; > | ~~~~~^~~~~~~~~~~ > ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: > note: at offset [1, 2] into destination object ‘keybuf’ of size 8 > 659 | keybuf[2]; > | ^~~~~~ > ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: > note: at offset [2, 3] into destination object ‘keybuf’ of size 8 > ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: > note: at offset [3, 4] into destination object ‘keybuf’ of size 8 > ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: > note: at offset [4, 5] into destination object ‘keybuf’ of size 8 > ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: > note: at offset [5, 6] into destination object ‘keybuf’ of size 8 > ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: > note: at offset [6, 7] into destination object ‘keybuf’ of size 8 > ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: > note: at offset [7, 8] into destination object ‘keybuf’ of size 8 > ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:675:22: > warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] > 675 | *q++ = *key << 1; > | ~~~~~^~~~~~~~~~~ > ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: > note: at offset 8 into destination object ‘keybuf’ of size 8 > 659 | keybuf[2]; > | ^~~~~~ > ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: > note: at offset [9, 10] into destination object ‘keybuf’ of size 8 > ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: > note: at offset [10, 11] into destination object ‘keybuf’ of size 8 > ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: > note: at offset [11, 12] into destination object ‘keybuf’ of size 8 > ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: > note: at offset [12, 13] into destination object ‘keybuf’ of size 8 > ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: > note: at offset [13, 14] into destination object ‘keybuf’ of size 8 > ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: > note: at offset [14, 15] into destination object ‘keybuf’ of size 8 > > > Luckily it turns out that that the warning is spurious, due to a bug in gcc > [1]. > > However, it took me quite a while to figure out what the hell the code was > doing: > > char * > px_crypt_des(const char *key, const char *setting) > { > uint32 keybuf[2]; > ... > uint8 *q; > ... > > /* > * Copy the key, shifting each character up by one bit and padding with > * zeros. > */ > q = (uint8 *) keybuf; > while (q - (uint8 *) keybuf - 8) > { > *q++ = *key << 1; > if (*key != '\0') > key++; > } > > Like, it's far from immediately obvious where the 8 is coming from (it's > the > size of keybuf), whether there are precedence issues or what this is even > trying to achieve. > > And it's still not clear to me why on earth it makes sense to write it that > complicated, when it seems something like > > for (int byteno = 0; byteno < sizeof(keybuf); byteno++) > { > *q++ = *key << 1; > if (*key != '\0') > key++; > } > > would do the same thing, except be trivially understandable for humans and > compilers. > > > Am I missing something or is what I suggest equivalent? Any reason to not > change it that way, both to clarify the code and to work around the > spurious > warning? > I got the warning with gcc-16 that you are pointing out. Your proposed rewrite looks equivalent to me. The current condition: q - (uint8 *) keybuf - 8 is a rather obscure way to say that the loop should stop once eight bytes have been written, and it seems plausible that gcc is getting confused by that form. There is one similar loop a little further down in the extended-DES path: while (q - (uint8 *) keybuf - 8 && *key) *q++ ^= *key++ << 1; That one did not warn in my build, probably because of the additional data-dependent "*key" condition, but it uses the same idiom. It might be worth rewriting both loops to use an explicit sizeof(keybuf)-bounded for loop, for readability and consistency. Regards, Ayush -
Re: Spurious warnings in crypto-des.c when building with gcc-16 -O3
Ayush Tiwari <ayushtiwari.slg01@gmail.com> — 2026-04-30T14:29:38Z
Hi, > > > On Wed, 29 Apr 2026 at 23:17, Andres Freund <andres@anarazel.de> wrote: > >> Hi, >> >> Recently I got a bit of a shock building postgres with gcc-16: >> >> ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c: >> In function ‘px_crypt_des’: >> ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:675:22: >> warning: writing 8 bytes into a region of size 7 [-Wstringop-overflow=] >> 675 | *q++ = *key << 1; >> | ~~~~~^~~~~~~~~~~ >> ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: >> note: at offset [1, 2] into destination object ‘keybuf’ of size 8 >> 659 | keybuf[2]; >> | ^~~~~~ >> ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: >> note: at offset [2, 3] into destination object ‘keybuf’ of size 8 >> ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: >> note: at offset [3, 4] into destination object ‘keybuf’ of size 8 >> ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: >> note: at offset [4, 5] into destination object ‘keybuf’ of size 8 >> ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: >> note: at offset [5, 6] into destination object ‘keybuf’ of size 8 >> ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: >> note: at offset [6, 7] into destination object ‘keybuf’ of size 8 >> ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: >> note: at offset [7, 8] into destination object ‘keybuf’ of size 8 >> ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:675:22: >> warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] >> 675 | *q++ = *key << 1; >> | ~~~~~^~~~~~~~~~~ >> ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: >> note: at offset 8 into destination object ‘keybuf’ of size 8 >> 659 | keybuf[2]; >> | ^~~~~~ >> ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: >> note: at offset [9, 10] into destination object ‘keybuf’ of size 8 >> ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: >> note: at offset [10, 11] into destination object ‘keybuf’ of size 8 >> ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: >> note: at offset [11, 12] into destination object ‘keybuf’ of size 8 >> ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: >> note: at offset [12, 13] into destination object ‘keybuf’ of size 8 >> ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: >> note: at offset [13, 14] into destination object ‘keybuf’ of size 8 >> ../../../../../home/andres/src/postgresql/contrib/pgcrypto/crypt-des.c:659:33: >> note: at offset [14, 15] into destination object ‘keybuf’ of size 8 >> >> >> Luckily it turns out that that the warning is spurious, due to a bug in >> gcc >> [1]. >> >> However, it took me quite a while to figure out what the hell the code was >> doing: >> >> char * >> px_crypt_des(const char *key, const char *setting) >> { >> uint32 keybuf[2]; >> ... >> uint8 *q; >> ... >> >> /* >> * Copy the key, shifting each character up by one bit and padding >> with >> * zeros. >> */ >> q = (uint8 *) keybuf; >> while (q - (uint8 *) keybuf - 8) >> { >> *q++ = *key << 1; >> if (*key != '\0') >> key++; >> } >> >> Like, it's far from immediately obvious where the 8 is coming from (it's >> the >> size of keybuf), whether there are precedence issues or what this is even >> trying to achieve. >> >> And it's still not clear to me why on earth it makes sense to write it >> that >> complicated, when it seems something like >> >> for (int byteno = 0; byteno < sizeof(keybuf); byteno++) >> { >> *q++ = *key << 1; >> if (*key != '\0') >> key++; >> } >> >> would do the same thing, except be trivially understandable for humans and >> compilers. >> >> I've created a patch for it. It replaces the obscure "while (q - (uint8 *) keybuf - 8)" loop conditions in px_crypt_des() with for-loops bounded by sizeof(keybuf). To avoid introducing a new -Wsign-compare warning against sizeof, I used the new loop counter (bytenum) as size_t. The logic remains equivalent, it preserves the exact iteration counts and the *key short-circuit in the extended-DES loop, but makes the bounds obvious to both readers and the compiler. Please find the patch attached. Thoughts? Regards, Ayush