Skip to content

Commit dbadc17

Browse files
dhowellsrustyrussell
authored andcommitted
X.509: Fix indefinite length element skip error handling
asn1_find_indefinite_length() returns an error indicator of -1, which the caller asn1_ber_decoder() places in a size_t (which is usually unsigned) and then checks to see whether it is less than 0 (which it can't be). This can lead to the following warning: lib/asn1_decoder.c:320 asn1_ber_decoder() warn: unsigned 'len' is never less than zero. Instead, asn1_find_indefinite_length() update the caller's idea of the data cursor and length separately from returning the error code. Reported-by: Dan Carpenter <[email protected]> Signed-off-by: David Howells <[email protected]> Signed-off-by: Rusty Russell <[email protected]>
1 parent 2f1c4fe commit dbadc17

File tree

1 file changed

+19
-9
lines changed

1 file changed

+19
-9
lines changed

lib/asn1_decoder.c

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,18 @@ static const unsigned char asn1_op_lengths[ASN1_OP__NR] = {
4646

4747
/*
4848
* Find the length of an indefinite length object
49+
* @data: The data buffer
50+
* @datalen: The end of the innermost containing element in the buffer
51+
* @_dp: The data parse cursor (updated before returning)
52+
* @_len: Where to return the size of the element.
53+
* @_errmsg: Where to return a pointer to an error message on error
4954
*/
5055
static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen,
51-
const char **_errmsg, size_t *_err_dp)
56+
size_t *_dp, size_t *_len,
57+
const char **_errmsg)
5258
{
5359
unsigned char tag, tmp;
54-
size_t dp = 0, len, n;
60+
size_t dp = *_dp, len, n;
5561
int indef_level = 1;
5662

5763
next_tag:
@@ -67,8 +73,11 @@ static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen
6773
/* It appears to be an EOC. */
6874
if (data[dp++] != 0)
6975
goto invalid_eoc;
70-
if (--indef_level <= 0)
71-
return dp;
76+
if (--indef_level <= 0) {
77+
*_len = dp - *_dp;
78+
*_dp = dp;
79+
return 0;
80+
}
7281
goto next_tag;
7382
}
7483

@@ -122,7 +131,7 @@ static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen
122131
missing_eoc:
123132
*_errmsg = "Missing EOC in indefinite len cons";
124133
error:
125-
*_err_dp = dp;
134+
*_dp = dp;
126135
return -1;
127136
}
128137

@@ -315,13 +324,14 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder,
315324
skip_data:
316325
if (!(flags & FLAG_CONS)) {
317326
if (flags & FLAG_INDEFINITE_LENGTH) {
318-
len = asn1_find_indefinite_length(
319-
data + dp, datalen - dp, &errmsg, &dp);
320-
if (len < 0)
327+
ret = asn1_find_indefinite_length(
328+
data, datalen, &dp, &len, &errmsg);
329+
if (ret < 0)
321330
goto error;
331+
} else {
332+
dp += len;
322333
}
323334
pr_debug("- LEAF: %zu\n", len);
324-
dp += len;
325335
}
326336
pc += asn1_op_lengths[op];
327337
goto next_op;

0 commit comments

Comments
 (0)