mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-27 12:57:53 +00:00
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 <dan.carpenter@oracle.com> Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
2f1c4fef10
commit
dbadc17683
1 changed files with 19 additions and 9 deletions
|
@ -46,12 +46,18 @@ static const unsigned char asn1_op_lengths[ASN1_OP__NR] = {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the length of an indefinite length object
|
* Find the length of an indefinite length object
|
||||||
|
* @data: The data buffer
|
||||||
|
* @datalen: The end of the innermost containing element in the buffer
|
||||||
|
* @_dp: The data parse cursor (updated before returning)
|
||||||
|
* @_len: Where to return the size of the element.
|
||||||
|
* @_errmsg: Where to return a pointer to an error message on error
|
||||||
*/
|
*/
|
||||||
static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen,
|
static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen,
|
||||||
const char **_errmsg, size_t *_err_dp)
|
size_t *_dp, size_t *_len,
|
||||||
|
const char **_errmsg)
|
||||||
{
|
{
|
||||||
unsigned char tag, tmp;
|
unsigned char tag, tmp;
|
||||||
size_t dp = 0, len, n;
|
size_t dp = *_dp, len, n;
|
||||||
int indef_level = 1;
|
int indef_level = 1;
|
||||||
|
|
||||||
next_tag:
|
next_tag:
|
||||||
|
@ -67,8 +73,11 @@ static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen
|
||||||
/* It appears to be an EOC. */
|
/* It appears to be an EOC. */
|
||||||
if (data[dp++] != 0)
|
if (data[dp++] != 0)
|
||||||
goto invalid_eoc;
|
goto invalid_eoc;
|
||||||
if (--indef_level <= 0)
|
if (--indef_level <= 0) {
|
||||||
return dp;
|
*_len = dp - *_dp;
|
||||||
|
*_dp = dp;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
goto next_tag;
|
goto next_tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +131,7 @@ static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen
|
||||||
missing_eoc:
|
missing_eoc:
|
||||||
*_errmsg = "Missing EOC in indefinite len cons";
|
*_errmsg = "Missing EOC in indefinite len cons";
|
||||||
error:
|
error:
|
||||||
*_err_dp = dp;
|
*_dp = dp;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,13 +324,14 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder,
|
||||||
skip_data:
|
skip_data:
|
||||||
if (!(flags & FLAG_CONS)) {
|
if (!(flags & FLAG_CONS)) {
|
||||||
if (flags & FLAG_INDEFINITE_LENGTH) {
|
if (flags & FLAG_INDEFINITE_LENGTH) {
|
||||||
len = asn1_find_indefinite_length(
|
ret = asn1_find_indefinite_length(
|
||||||
data + dp, datalen - dp, &errmsg, &dp);
|
data, datalen, &dp, &len, &errmsg);
|
||||||
if (len < 0)
|
if (ret < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
} else {
|
||||||
|
dp += len;
|
||||||
}
|
}
|
||||||
pr_debug("- LEAF: %zu\n", len);
|
pr_debug("- LEAF: %zu\n", len);
|
||||||
dp += len;
|
|
||||||
}
|
}
|
||||||
pc += asn1_op_lengths[op];
|
pc += asn1_op_lengths[op];
|
||||||
goto next_op;
|
goto next_op;
|
||||||
|
|
Loading…
Reference in a new issue