From dbadc17683e6c673a69b236c0f041b931cc55c42 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 4 Oct 2012 14:21:23 +0100 Subject: 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 Signed-off-by: David Howells Signed-off-by: Rusty Russell --- lib/asn1_decoder.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c index 2e4196ddf06f..de2c8b5a715b 100644 --- a/lib/asn1_decoder.c +++ b/lib/asn1_decoder.c @@ -46,12 +46,18 @@ static const unsigned char asn1_op_lengths[ASN1_OP__NR] = { /* * 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, - const char **_errmsg, size_t *_err_dp) + size_t *_dp, size_t *_len, + const char **_errmsg) { unsigned char tag, tmp; - size_t dp = 0, len, n; + size_t dp = *_dp, len, n; int indef_level = 1; next_tag: @@ -67,8 +73,11 @@ next_tag: /* It appears to be an EOC. */ if (data[dp++] != 0) goto invalid_eoc; - if (--indef_level <= 0) - return dp; + if (--indef_level <= 0) { + *_len = dp - *_dp; + *_dp = dp; + return 0; + } goto next_tag; } @@ -122,7 +131,7 @@ data_overrun_error: missing_eoc: *_errmsg = "Missing EOC in indefinite len cons"; error: - *_err_dp = dp; + *_dp = dp; return -1; } @@ -315,13 +324,14 @@ next_op: skip_data: if (!(flags & FLAG_CONS)) { if (flags & FLAG_INDEFINITE_LENGTH) { - len = asn1_find_indefinite_length( - data + dp, datalen - dp, &errmsg, &dp); - if (len < 0) + ret = asn1_find_indefinite_length( + data, datalen, &dp, &len, &errmsg); + if (ret < 0) goto error; + } else { + dp += len; } pr_debug("- LEAF: %zu\n", len); - dp += len; } pc += asn1_op_lengths[op]; goto next_op; -- cgit v1.2.3