Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dbadc176 authored by David Howells's avatar David Howells Committed by Rusty Russell
Browse files

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: default avatarDan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 2f1c4fef
Loading
Loading
Loading
Loading
+19 −9
Original line number Diff line number Diff line
@@ -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;