You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Notes mainly to myself. I've run out of steam right now, but I'll come back to it later (albeit possibly after clang 12.0 is out).
The clang static analyzer produces the scary-looking:
../../crypto/crypto_aesctr_shared.c:47:30: warning: The right operand of '^' is a garbage value [core.UndefinedBinaryOperatorResult]
(*outbuf)[i] = (*inbuf)[i] ^ stream->buf[bytemod + i];
^ ~~~~~~~~~~~~~~~~~~~~~~~~
1 warning generated.
The first instance of this arose in 9ff90c2, which is baffling since there's nothing there that would suggest this flaw.
Tracing it backwards, it appears that the analyzer doesn't believe that be64enc() initializes the memory. This is even true if we use #include <sys/endian.h> intsead of our own be64enc.
Then we get this warning instead of the original one:
../../crypto/crypto_aesctr_shared.c:35:17: warning: Assigned value is garbage or undefined [core.uninitialized.Assign]
stream->buf[0] = stream->buf[0];
^ ~~~~~~~~~~~~~~
1 warning generated.
So at least it doesn't have anything to do with using the cipherblock.
We can silence the warning entirely by doing:
diff --git a/crypto/crypto_aesctr.c b/crypto/crypto_aesctr.c
index 2b4e018e..b6483f29 100644
--- a/crypto/crypto_aesctr.c
+++ b/crypto/crypto_aesctr.c
@@ -86,6 +86,10 @@ crypto_aesctr_init2(struct crypto_aesctr * stream,
be64enc(stream->pblk, nonce);
stream->bytectr = 0;
+ /* Silence the warning?!?! */
+ for (int i = 0; i < 4; i++)
+ stream->pblk[i] = stream->pblk[i];
+
/*
* Set the counter such that the least significant byte will wrap once
* incremented.
This should be a no-op, but it's enough to make clang realize that we've initialized the first 4 bytes of stream->pblk. (And yes, we must use i < 4; 3 is not enough.)
So: it appears that clang's static analyzer isn't convinced that be64enc() initializes the first 32 bits of its output. I wonder if this it's getting caught up in the compiler's "try to recognize a byte-swap" code? The assembly output shows that it did recognize it as a byte-swap:
So maybe there's a convoluted path of the analyzer recognizing that the first 4 bytes come from nonce >> 32, noticing that the hard-coded nonce in our test file isn't bigger than 2^32, and then... forgetting that a right-shift will introduce 0s, and is thus well-defined? Hmm, no, that's nonsense. At least, if it was the case, we'd see these warnings in earlier versions of our code, not introduced at that particular commit.
FWIW, I see this warning on linux t4g as well, so it's not just a FreeBSD amd64 thing.
The text was updated successfully, but these errors were encountered:
(I won't be proposing that fix for merging, because we don't want to clutter our code with #ifdefs for specific compilers / tools, and this isn't important enough to warrant a POSIXFAIL define.)
EDIT: confirmed that clang 13 also has this bug.
gperciva
changed the title
False warning from clang-scan, likely from be64enc
False clang-scan warning, likely from be64enc
Dec 3, 2021
Notes mainly to myself. I've run out of steam right now, but I'll come back to it later (albeit possibly after clang 12.0 is out).
The clang static analyzer produces the scary-looking:
The first instance of this arose in 9ff90c2, which is baffling since there's nothing there that would suggest this flaw.
Tracing it backwards, it appears that the analyzer doesn't believe that
be64enc()
initializes the memory. This is even true if we use#include <sys/endian.h>
intsead of our ownbe64enc
.Then we get this warning instead of the original one:
So at least it doesn't have anything to do with using the cipherblock.
This should be a no-op, but it's enough to make clang realize that we've initialized the first 4 bytes of
stream->pblk
. (And yes, we must usei < 4
; 3 is not enough.)So: it appears that clang's static analyzer isn't convinced that
be64enc()
initializes the first 32 bits of its output. I wonder if this it's getting caught up in the compiler's "try to recognize a byte-swap" code? The assembly output shows that it did recognize it as a byte-swap:but I know that some implementations do a pair of
be32enc()
. For example, FreeBSD's/usr/include/sys/endian.h
contains the alignment-agnostic:So maybe there's a convoluted path of the analyzer recognizing that the first 4 bytes come from
nonce >> 32
, noticing that the hard-coded nonce in our test file isn't bigger than 2^32, and then... forgetting that a right-shift will introduce 0s, and is thus well-defined? Hmm, no, that's nonsense. At least, if it was the case, we'd see these warnings in earlier versions of our code, not introduced at that particular commit.FWIW, I see this warning on linux t4g as well, so it's not just a FreeBSD amd64 thing.
The text was updated successfully, but these errors were encountered: