From: Michael Haggerty <hidden> Date: 2017-08-26 08:28:31
While putzing around in the notes code quite some time ago, I found
this comment:
/*
* Determine full path for this non-note entry:
* The filename is already found in entry.path, but the
* directory part of the path must be deduced from the subtree
* containing this entry. We assume here that the overall notes
* tree follows a strict byte-based progressive fanout
* structure (i.e. using 2/38, 2/2/36, etc. fanouts, and not
* e.g. 4/36 fanout). This means that if a non-note is found at
* path "dead/beef", the following code will register it as
* being found on "de/ad/beef".
* On the other hand, if you use such non-obvious non-note
* paths in the middle of a notes tree, you deserve what's
* coming to you ;). Note that for non-notes that are not
* SHA1-like at the top level, there will be no problems.
*
* To conclude, it is strongly advised to make sure non-notes
* have at least one non-hex character in the top-level path
* component.
*/
This was enough of a nerd snipe to get me to dig into the code.
It turns out that the comment is incorrect, but there was nevertheless
plenty that could be cleaned up in the area:
* Make macro `GIT_NIBBLE` safer by adding some parentheses
* Remove some dead code
* Fix some memory leaks
* Fix some obsolete and incorrect comments
* Reject "notes" that are not blobs
I hope the result is also easier to understand.
This branch is also available from my Git fork [1] as branch
`load-subtree-cleanup`.
Michael
[1] https://github.com/mhagger/git
Michael Haggerty (12):
notes: make GET_NIBBLE macro more robust
load_subtree(): remove unnecessary conditional
load_subtree(): reduce the scope of some local variables
load_subtree(): fix incorrect comment
load_subtree(): separate logic for internal vs. terminal entries
load_subtree(): check earlier whether an internal node is a tree entry
load_subtree(): only consider blobs to be potential notes
get_oid_hex_segment(): return 0 on success
load_subtree(): combine some common code
get_oid_hex_segment(): don't pad the rest of `oid`
hex_to_bytes(): simpler replacement for `get_oid_hex_segment()`
load_subtree(): declare some variables to be `size_t`
notes.c | 136 +++++++++++++++++++++++++++++++---------------------------------
1 file changed, 66 insertions(+), 70 deletions(-)
--
2.11.0
From: Michael Haggerty <hidden> Date: 2017-08-26 08:28:33
Put parentheses around sha1. Otherwise it could fail for something
like
GET_NIBBLE(n, (unsigned char *)data);
Signed-off-by: Michael Haggerty <redacted>
---
notes.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
From: Michael Haggerty <hidden> Date: 2017-08-26 08:28:35
Declare the variables inside the loop, to make it more obvious that
their values are not carried across loop iterations.
Signed-off-by: Michael Haggerty <redacted>
---
notes.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
From: Michael Haggerty <hidden> Date: 2017-08-26 08:28:37
This comment was added in 851c2b3791 (Teach notes code to properly
preserve non-notes in the notes tree, 2010-02-13) when the
corresponding code was added. But I believe it was incorrect even
then. The condition `path_len != 2` a dozen lines up prevents a path
like "dead/beef" from being converted to "de/ad/beef", and indeed the
test added in commit 851c2b3 verifies that this case works correctly.
Signed-off-by: Michael Haggerty <redacted>
---
notes.c | 24 +++++++-----------------
1 file changed, 7 insertions(+), 17 deletions(-)
From: Michael Haggerty <hidden> Date: 2017-08-26 08:28:40
If an entry is not a tree entry, then it cannot possibly be an
internal node. But the old code checked this condition only after
allocating a leaf_node object and therefore leaked that memory.
Instead, check before even entering this branch of the code.
Signed-off-by: Michael Haggerty <redacted>
---
notes.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
@@ -449,6 +449,11 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,oidcpy(&l->val_oid,entry.oid);}elseif(path_len==2){/* This is potentially an internal node */++if(!S_ISDIR(entry.mode))+/* internal nodes must be trees */+gotohandle_non_note;+if(get_oid_hex_segment(entry.path,2,object_oid.hash+prefix_len,GIT_SHA1_RAWSZ-prefix_len)<0)
@@ -459,8 +464,6 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,xcalloc(1,sizeof(structleaf_node));oidcpy(&l->key_oid,&object_oid);oidcpy(&l->val_oid,entry.oid);-if(!S_ISDIR(entry.mode))-gotohandle_non_note;/* not subtree */l->key_oid.hash[KEY_INDEX]=(unsignedchar)(prefix_len+1);}else{/* This can't be part of a note */
From: Michael Haggerty <hidden> Date: 2017-08-26 08:28:43
Nobody cares about the return value of get_oid_hex_segment() except to
check whether it failed. So just return 0 on success.
And while we're updating its docstring, update it for some argument
renaming that happened a while ago.
Signed-off-by: Michael Haggerty <redacted>
---
notes.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
From: Michael Haggerty <hidden> Date: 2017-08-26 08:28:54
Remove the feature of `get_oid_hex_segment()` that it pads the rest of
the `oid` argument with zeros. Instead, do this at the caller who
needs it.
This makes the functionality of this function more coherent and
removes the need for its `oid_len` argument.
Signed-off-by: Michael Haggerty <redacted>
---
notes.c | 24 +++++++++++++-----------
1 file changed, 13 insertions(+), 11 deletions(-)
@@ -356,8 +355,6 @@ static int get_oid_hex_segment(const char *hex, unsigned int hex_len,*oid++=val;hex+=2;}-for(;i<oid_len;i++)-*oid++=0;return0;}
@@ -442,24 +439,29 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,gotohandle_non_note;if(get_oid_hex_segment(entry.path,path_len,-object_oid.hash+prefix_len,-GIT_SHA1_RAWSZ-prefix_len))+object_oid.hash+prefix_len))gotohandle_non_note;/* entry.path is not a SHA1 */type=PTR_TYPE_NOTE;}elseif(path_len==2){/* This is potentially an internal node */+size_tlen=prefix_len;if(!S_ISDIR(entry.mode))/* internal nodes must be trees */gotohandle_non_note;if(get_oid_hex_segment(entry.path,2,-object_oid.hash+prefix_len,-GIT_SHA1_RAWSZ-prefix_len))+object_oid.hash+len++))gotohandle_non_note;/* entry.path is not a SHA1 */-object_oid.hash[KEY_INDEX]=(unsignedchar)(prefix_len+1);+/*+*PadtherestoftheSHA-1withzeros,+*exceptforthelastbyte,wherewewrite+*thelength:+*/+memset(object_oid.hash+len,0,GIT_SHA1_RAWSZ-len-1);+object_oid.hash[KEY_INDEX]=(unsignedchar)len;type=PTR_TYPE_SUBTREE;}else{
From: Michael Haggerty <hidden> Date: 2017-08-26 08:28:55
Now that `get_oid_hex_segment()` does less, it makes sense to rename
it and simplify its semantics:
* Instead of a `hex_len` parameter, which was the number of hex
characters (and had to be even), use a `len` parameter, which is the
number of resulting bytes. This removes then need for the check that
`hex_len` is even and to divide it by two to determine the number of
bytes. For good hygiene, declare the `len` parameter to be `size_t`
instead of `unsigned int`.
* Change the order of the arguments to the more traditional (dst,
src, len).
* Rename the function to `hex_to_bytes()`.
* Remove a loop variable: just count `len` down instead.
Signed-off-by: Michael Haggerty <redacted>
---
notes.c | 28 ++++++++++------------------
1 file changed, 10 insertions(+), 18 deletions(-)
@@ -438,8 +431,8 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,/* notes must be blobs */gotohandle_non_note;-if(get_oid_hex_segment(entry.path,path_len,-object_oid.hash+prefix_len))+if(hex_to_bytes(object_oid.hash+prefix_len,entry.path,+GIT_SHA1_RAWSZ-prefix_len))gotohandle_non_note;/* entry.path is not a SHA1 */type=PTR_TYPE_NOTE;
@@ -451,8 +444,7 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,/* internal nodes must be trees */gotohandle_non_note;-if(get_oid_hex_segment(entry.path,2,-object_oid.hash+len++))+if(hex_to_bytes(object_oid.hash+len++,entry.path,1))gotohandle_non_note;/* entry.path is not a SHA1 *//*
@@ -422,7 +422,7 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,while(tree_entry(&desc,&entry)){unsignedchartype;structleaf_node*l;-intpath_len=strlen(entry.path);+size_tpath_len=strlen(entry.path);if(path_len==2*(GIT_SHA1_RAWSZ-prefix_len)){/* This is potentially the remainder of the SHA-1 */
From: Michael Haggerty <hidden> Date: 2017-08-26 08:28:58
The old code converted any entry whose path constituted a full SHA-1
as a leaf node, without regard for the type of the entry. But only
blobs can be notes. So treat entries whose paths *look like* notes
paths but that are not blobs as non-notes.
Signed-off-by: Michael Haggerty <redacted>
---
notes.c | 5 +++++
1 file changed, 5 insertions(+)
@@ -437,6 +437,11 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,if(path_len==2*(GIT_SHA1_RAWSZ-prefix_len)){/* This is potentially the remainder of the SHA-1 */++if(!S_ISREG(entry.mode))+/* notes must be blobs */+gotohandle_non_note;+if(get_oid_hex_segment(entry.path,path_len,object_oid.hash+prefix_len,GIT_SHA1_RAWSZ-prefix_len)<0)
From: Michael Haggerty <hidden> Date: 2017-08-26 08:29:00
There are only two legitimate notes path components:
* A hexadecimal string that fills the rest of the SHA-1
* A two-digit hexadecimal string that constitutes another internal
node.
So handle those two cases at the top level, and reject others as
non-notes without trying to parse them. The logic separation also
simplifies upcoming changes.
This prevents us from leaking memory for a leaf_node in the case of
wrong-sized paths. There are still memory leaks in this code; they will
be fixed in upcoming commits.
Signed-off-by: Michael Haggerty <redacted>
---
notes.c | 52 +++++++++++++++++++++++++++++++---------------------
1 file changed, 31 insertions(+), 21 deletions(-)
@@ -433,30 +433,40 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,while(tree_entry(&desc,&entry)){unsignedchartype;structleaf_node*l;-intlen,path_len=strlen(entry.path);+intpath_len=strlen(entry.path);++if(path_len==2*(GIT_SHA1_RAWSZ-prefix_len)){+/* This is potentially the remainder of the SHA-1 */+if(get_oid_hex_segment(entry.path,path_len,+object_oid.hash+prefix_len,+GIT_SHA1_RAWSZ-prefix_len)<0)+gotohandle_non_note;/* entry.path is not a SHA1 */++type=PTR_TYPE_NOTE;+l=(structleaf_node*)+xcalloc(1,sizeof(structleaf_node));+oidcpy(&l->key_oid,&object_oid);+oidcpy(&l->val_oid,entry.oid);+}elseif(path_len==2){+/* This is potentially an internal node */+if(get_oid_hex_segment(entry.path,2,+object_oid.hash+prefix_len,+GIT_SHA1_RAWSZ-prefix_len)<0)+gotohandle_non_note;/* entry.path is not a SHA1 */-len=get_oid_hex_segment(entry.path,path_len,-object_oid.hash+prefix_len,GIT_SHA1_RAWSZ-prefix_len);-if(len<0)-gotohandle_non_note;/* entry.path is not a SHA1 */-len+=prefix_len;--/*-*IfobjectSHA1iscomplete(len==20),assumenoteobject-*IfobjectSHA1isincomplete(len<20),andcurrent-*componentconsistsof2hexchars,assumenotesubtree-*/-type=PTR_TYPE_NOTE;-l=(structleaf_node*)-xcalloc(1,sizeof(structleaf_node));-oidcpy(&l->key_oid,&object_oid);-oidcpy(&l->val_oid,entry.oid);-if(len<GIT_SHA1_RAWSZ){-if(!S_ISDIR(entry.mode)||path_len!=2)-gotohandle_non_note;/* not subtree */-l->key_oid.hash[KEY_INDEX]=(unsignedchar)len;type=PTR_TYPE_SUBTREE;+l=(structleaf_node*)+xcalloc(1,sizeof(structleaf_node));+oidcpy(&l->key_oid,&object_oid);+oidcpy(&l->val_oid,entry.oid);+if(!S_ISDIR(entry.mode))+gotohandle_non_note;/* not subtree */+l->key_oid.hash[KEY_INDEX]=(unsignedchar)(prefix_len+1);+}else{+/* This can't be part of a note */+gotohandle_non_note;}+if(note_tree_insert(t,node,n,l,type,combine_notes_concatenate))die("Failed to load %s %s into notes tree "
From: Michael Haggerty <hidden> Date: 2017-08-26 08:29:02
Write the length into `object_oid` (before copying) rather than
`l->key_oid` (after copying). Then combine some code from the two `if`
blocks.
Signed-off-by: Michael Haggerty <redacted>
---
notes.c | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)
@@ -447,10 +447,6 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,gotohandle_non_note;/* entry.path is not a SHA1 */type=PTR_TYPE_NOTE;-l=(structleaf_node*)-xcalloc(1,sizeof(structleaf_node));-oidcpy(&l->key_oid,&object_oid);-oidcpy(&l->val_oid,entry.oid);}elseif(path_len==2){/* This is potentially an internal node */
@@ -463,17 +459,17 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,GIT_SHA1_RAWSZ-prefix_len))gotohandle_non_note;/* entry.path is not a SHA1 */+object_oid.hash[KEY_INDEX]=(unsignedchar)(prefix_len+1);+type=PTR_TYPE_SUBTREE;-l=(structleaf_node*)-xcalloc(1,sizeof(structleaf_node));-oidcpy(&l->key_oid,&object_oid);-oidcpy(&l->val_oid,entry.oid);-l->key_oid.hash[KEY_INDEX]=(unsignedchar)(prefix_len+1);}else{/* This can't be part of a note */gotohandle_non_note;}+l=xcalloc(1,sizeof(*l));+oidcpy(&l->key_oid,&object_oid);+oidcpy(&l->val_oid,entry.oid);if(note_tree_insert(t,node,n,l,type,combine_notes_concatenate))die("Failed to load %s %s into notes tree "
From: Michael Haggerty <hidden> Date: 2017-08-26 08:29:04
At this point in the code, len is *always* <= 20.
Signed-off-by: Michael Haggerty <redacted>
---
notes.c | 35 +++++++++++++++++------------------
1 file changed, 17 insertions(+), 18 deletions(-)
@@ -446,25 +446,24 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,*IfobjectSHA1isincomplete(len<20),andcurrent*componentconsistsof2hexchars,assumenotesubtree*/-if(len<=GIT_SHA1_RAWSZ){-type=PTR_TYPE_NOTE;-l=(structleaf_node*)-xcalloc(1,sizeof(structleaf_node));-oidcpy(&l->key_oid,&object_oid);-oidcpy(&l->val_oid,entry.oid);-if(len<GIT_SHA1_RAWSZ){-if(!S_ISDIR(entry.mode)||path_len!=2)-gotohandle_non_note;/* not subtree */-l->key_oid.hash[KEY_INDEX]=(unsignedchar)len;-type=PTR_TYPE_SUBTREE;-}-if(note_tree_insert(t,node,n,l,type,-combine_notes_concatenate))-die("Failed to load %s %s into notes tree "-"from %s",-type==PTR_TYPE_NOTE?"note":"subtree",-oid_to_hex(&l->key_oid),t->ref);+type=PTR_TYPE_NOTE;+l=(structleaf_node*)+xcalloc(1,sizeof(structleaf_node));+oidcpy(&l->key_oid,&object_oid);+oidcpy(&l->val_oid,entry.oid);+if(len<GIT_SHA1_RAWSZ){+if(!S_ISDIR(entry.mode)||path_len!=2)+gotohandle_non_note;/* not subtree */+l->key_oid.hash[KEY_INDEX]=(unsignedchar)len;+type=PTR_TYPE_SUBTREE;}+if(note_tree_insert(t,node,n,l,type,+combine_notes_concatenate))+die("Failed to load %s %s into notes tree "+"from %s",+type==PTR_TYPE_NOTE?"note":"subtree",+oid_to_hex(&l->key_oid),t->ref);+continue;handle_non_note:
From: Johan Herland <hidden> Date: 2017-08-26 23:56:20
On Sat, Aug 26, 2017 at 10:28 AM, Michael Haggerty [off-list ref] wrote:
[...]
plenty that could be cleaned up in the area:
* Make macro `GIT_NIBBLE` safer by adding some parentheses
* Remove some dead code
* Fix some memory leaks
* Fix some obsolete and incorrect comments
* Reject "notes" that are not blobs
I hope the result is also easier to understand.
I looked through the series, and the patches look good to me, although
I do agree with Junio's comments on #2.
Thanks for a long-overdue cleanup in one of the hairier parts of
the notes code. The end result reads a lot better IMHO.
...Johan
From: Jeff King <hidden> Date: 2017-09-09 10:31:38
On Sat, Aug 26, 2017 at 10:28:00AM +0200, Michael Haggerty wrote:
It turns out that the comment is incorrect, but there was nevertheless
plenty that could be cleaned up in the area:
* Make macro `GIT_NIBBLE` safer by adding some parentheses
* Remove some dead code
* Fix some memory leaks
* Fix some obsolete and incorrect comments
* Reject "notes" that are not blobs
I hope the result is also easier to understand.
This branch is also available from my Git fork [1] as branch
`load-subtree-cleanup`.
FYI, Coverity seems to complain about "pu" after this series is merged, but
I think it's wrong. It says:
*** CID 1417630: Memory - illegal accesses (OVERRUN)
/notes.c: 458 in load_subtree()
452
453 /*
454 * Pad the rest of the SHA-1 with zeros,
455 * except for the last byte, where we write
456 * the length:
457 */
>>> CID 1417630: Memory - illegal accesses (OVERRUN)
>>> Overrunning array of 20 bytes at byte offset 20 by dereferencing pointer "&object_oid.hash[len]".
458 memset(object_oid.hash + len, 0, GIT_SHA1_RAWSZ - len - 1);
459 object_oid.hash[KEY_INDEX] = (unsigned char)len;
460
461 type = PTR_TYPE_SUBTREE;
462 } else {
463 /* This can't be part of a note */
I agree that if "len" were 20 here that would be a problem, but I don't
think that's possible.
The tool correctly claims that prefix_len can be up to 19, due to the
assert:
3. cond_at_most: Checking prefix_len >= 20UL implies that prefix_len may be up to 19 on the false branch.
420 if (prefix_len >= GIT_SHA1_RAWSZ)
421 BUG("prefix_len (%"PRIuMAX") is out of range", (uintmax_t)prefix_len);
Then it claims:
13. Condition path_len == 2 * (20 - prefix_len), taking false branch.
430 if (path_len == 2 * (GIT_SHA1_RAWSZ - prefix_len)) {
431 /* This is potentially the remainder of the SHA-1 */
So we know that either prefix_len is not 19, or that path_len is not 2
(since that combination would cause us to take the true branch here).
But then it goes on to say:
14. Condition path_len == 2, taking true branch.
442 } else if (path_len == 2) {
443 /* This is potentially an internal node */
which I believe must mean that prefix_len cannot be 19 here. And yet it
says:
15. assignment: Assigning: len = prefix_len. The value of len may now be up to 19.
444 size_t len = prefix_len;
445
[...]
17. incr: Incrementing len. The value of len may now be up to 20.
18. Condition hex_to_bytes(&object_oid.hash[len++], entry.path, 1), taking false branch.
450 if (hex_to_bytes(object_oid.hash + len++, entry.path, 1))
451 goto handle_non_note; /* entry.path is not a SHA1 */
I think that's impossible, and Coverity simply isn't smart enough to
shrink the set of possible values for prefix_len based on the set of
if-else conditions.
So nothing to see here, but since I spent 20 minutes scratching my head
(and I know others look at Coverity output and may scratch their heads
too), I thought it was worth writing up. And also if I'm wrong, it would
be good to know. ;)
-Peff
From: Michael Haggerty <hidden> Date: 2017-09-10 04:45:19
On 09/09/2017 12:31 PM, Jeff King wrote:
On Sat, Aug 26, 2017 at 10:28:00AM +0200, Michael Haggerty wrote:
quoted
It turns out that the comment is incorrect, but there was nevertheless
plenty that could be cleaned up in the area:
* Make macro `GIT_NIBBLE` safer by adding some parentheses
* Remove some dead code
* Fix some memory leaks
* Fix some obsolete and incorrect comments
* Reject "notes" that are not blobs
I hope the result is also easier to understand.
This branch is also available from my Git fork [1] as branch
`load-subtree-cleanup`.
FYI, Coverity seems to complain about "pu" after this series is merged, but
I think it's wrong. It says:
*** CID 1417630: Memory - illegal accesses (OVERRUN)
/notes.c: 458 in load_subtree()
452
453 /*
454 * Pad the rest of the SHA-1 with zeros,
455 * except for the last byte, where we write
456 * the length:
457 */
>>> CID 1417630: Memory - illegal accesses (OVERRUN)
>>> Overrunning array of 20 bytes at byte offset 20 by dereferencing pointer "&object_oid.hash[len]".
458 memset(object_oid.hash + len, 0, GIT_SHA1_RAWSZ - len - 1);
459 object_oid.hash[KEY_INDEX] = (unsigned char)len;
460
461 type = PTR_TYPE_SUBTREE;
462 } else {
463 /* This can't be part of a note */
I agree that if "len" were 20 here that would be a problem, but I don't
think that's possible.
The tool correctly claims that prefix_len can be up to 19, due to the
assert:
3. cond_at_most: Checking prefix_len >= 20UL implies that prefix_len may be up to 19 on the false branch.
420 if (prefix_len >= GIT_SHA1_RAWSZ)
421 BUG("prefix_len (%"PRIuMAX") is out of range", (uintmax_t)prefix_len);
Then it claims:
13. Condition path_len == 2 * (20 - prefix_len), taking false branch.
430 if (path_len == 2 * (GIT_SHA1_RAWSZ - prefix_len)) {
431 /* This is potentially the remainder of the SHA-1 */
So we know that either prefix_len is not 19, or that path_len is not 2
(since that combination would cause us to take the true branch here).
But then it goes on to say:
14. Condition path_len == 2, taking true branch.
442 } else if (path_len == 2) {
443 /* This is potentially an internal node */
which I believe must mean that prefix_len cannot be 19 here. And yet it
says:
15. assignment: Assigning: len = prefix_len. The value of len may now be up to 19.
444 size_t len = prefix_len;
445
[...]
17. incr: Incrementing len. The value of len may now be up to 20.
18. Condition hex_to_bytes(&object_oid.hash[len++], entry.path, 1), taking false branch.
450 if (hex_to_bytes(object_oid.hash + len++, entry.path, 1))
451 goto handle_non_note; /* entry.path is not a SHA1 */
I think that's impossible, and Coverity simply isn't smart enough to
shrink the set of possible values for prefix_len based on the set of
if-else conditions.
So nothing to see here, but since I spent 20 minutes scratching my head
(and I know others look at Coverity output and may scratch their heads
too), I thought it was worth writing up. And also if I'm wrong, it would
be good to know. ;)
Thanks for looking into this. I agree with your analysis.
I wonder whether it is the factor of two between path lengths and byte
lengths that is confusing Coverity. Perhaps the patch below would help.
It requires an extra, superfluous, check, but perhaps makes the code a
tad more readable. I'm neutral on whether we would want to make the change.
Is there a way to ask Coverity whether a hypothetical change would
remove the warning, short of merging the change to master?
Michael
struct leaf_node *subtree,
goto handle_non_note; /* entry.path is not a SHA1 */
type = PTR_TYPE_NOTE;
- } else if (path_len == 2) {
+ } else if (path_bytes == 1) {
/* This is potentially an internal node */
size_t len = prefix_len;
From: Jeff King <hidden> Date: 2017-09-10 07:39:34
On Sun, Sep 10, 2017 at 06:45:08AM +0200, Michael Haggerty wrote:
quoted
So nothing to see here, but since I spent 20 minutes scratching my head
(and I know others look at Coverity output and may scratch their heads
too), I thought it was worth writing up. And also if I'm wrong, it would
be good to know. ;)
Thanks for looking into this. I agree with your analysis.
I wonder whether it is the factor of two between path lengths and byte
lengths that is confusing Coverity. Perhaps the patch below would help.
It requires an extra, superfluous, check, but perhaps makes the code a
tad more readable. I'm neutral on whether we would want to make the change.
Yeah, I do agree that it makes the code's assumptions a bit easier to
follow.
Is there a way to ask Coverity whether a hypothetical change would
remove the warning, short of merging the change to master?
You can download and run the build portion of the coverity tools
yourself. IIRC, that pushes the build up to their servers which then do
the analysis (you can make your own "project", or use the existing "git"
project -- I checked and you are already listed as an admin). I recall
it being a minor pain to get it set up, but not too bad.
Stefan runs it against "pu" on a regular basis, which is where the
emailed results come from. So just having Junio merge it to "pu" would
be enough to get results.
I noticed that they now have some GitHub/Travis integration:
https://scan.coverity.com/github
I'm not sure if that is new, or if we just didn't notice it before. ;)
But that probably makes more sense to use than ad-hoc uploading (and
maybe it would make it easy for you to test personal branches, too).
-Peff
From: Michael Haggerty <hidden> Date: 2017-09-12 06:47:25
On Sun, Sep 10, 2017 at 9:39 AM, Jeff King [off-list ref] wrote:
On Sun, Sep 10, 2017 at 06:45:08AM +0200, Michael Haggerty wrote:
quoted
quoted
So nothing to see here, but since I spent 20 minutes scratching my head
(and I know others look at Coverity output and may scratch their heads
too), I thought it was worth writing up. And also if I'm wrong, it would
be good to know. ;)
Thanks for looking into this. I agree with your analysis.
I wonder whether it is the factor of two between path lengths and byte
lengths that is confusing Coverity. Perhaps the patch below would help.
It requires an extra, superfluous, check, but perhaps makes the code a
tad more readable. I'm neutral on whether we would want to make the change.
Yeah, I do agree that it makes the code's assumptions a bit easier to
follow.
quoted
Is there a way to ask Coverity whether a hypothetical change would
remove the warning, short of merging the change to master?
You can download and run the build portion of the coverity tools
yourself. [...]
Thanks for the info.
My suggested tweak doesn't appease Coverity. Given that, I don't think
I'll bother adding it to the patch series.
Michael
From: Lars Schneider <hidden> Date: 2017-09-12 11:55:55
On 10 Sep 2017, at 09:39, Jeff King [off-list ref] wrote:
On Sun, Sep 10, 2017 at 06:45:08AM +0200, Michael Haggerty wrote:
quoted
quoted
So nothing to see here, but since I spent 20 minutes scratching my head
(and I know others look at Coverity output and may scratch their heads
too), I thought it was worth writing up. And also if I'm wrong, it would
be good to know. ;)
Thanks for looking into this. I agree with your analysis.
I wonder whether it is the factor of two between path lengths and byte
lengths that is confusing Coverity. Perhaps the patch below would help.
It requires an extra, superfluous, check, but perhaps makes the code a
tad more readable. I'm neutral on whether we would want to make the change.
Yeah, I do agree that it makes the code's assumptions a bit easier to
follow.
quoted
Is there a way to ask Coverity whether a hypothetical change would
remove the warning, short of merging the change to master?
You can download and run the build portion of the coverity tools
yourself. IIRC, that pushes the build up to their servers which then do
the analysis (you can make your own "project", or use the existing "git"
project -- I checked and you are already listed as an admin). I recall
it being a minor pain to get it set up, but not too bad.
Stefan runs it against "pu" on a regular basis, which is where the
emailed results come from. So just having Junio merge it to "pu" would
be enough to get results.
I noticed that they now have some GitHub/Travis integration:
https://scan.coverity.com/github
I'm not sure if that is new, or if we just didn't notice it before. ;)
But that probably makes more sense to use than ad-hoc uploading (and
maybe it would make it easy for you to test personal branches, too).
Coverity scans Git already:
https://scan.coverity.com/projects/70
I requested access to this Coverity project to integrate into our TravisCI
build.
- Lars