Make X509V3_get_value_int free the old value before overwriting it.
This is an unexported API, so it's okay to change it. Many extension
types work by parsing a list of key:value pairs and then setting fields
based on it. If a key appears twice, it'll just overwrite the old value.
But X509V3_get_value_int forgot to free the old value when doing so.
Bug: oss-fuzz:55572
Change-Id: I2b39aa7e9214e82fb40ee2e3481697338fe88e1a
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/56745
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc
index 0928d46..9abe953 100644
--- a/crypto/x509/x509_test.cc
+++ b/crypto/x509/x509_test.cc
@@ -5706,6 +5706,19 @@
{0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05,
0x30, 0x03, 0x01, 0x01, 0xff}},
+ {"basicConstraints",
+ "critical,CA:true,pathlen:1",
+ nullptr,
+ {0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
+ 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01}},
+
+ // key:value tuples can be repeated and just override the previous value.
+ {"basicConstraints",
+ "critical,CA:true,pathlen:100,pathlen:1",
+ nullptr,
+ {0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
+ 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01}},
+
// Extension contents may be referenced from a config section.
{"basicConstraints",
"critical,@section",
diff --git a/crypto/x509v3/internal.h b/crypto/x509v3/internal.h
index 05a7026..0c068a0 100644
--- a/crypto/x509v3/internal.h
+++ b/crypto/x509v3/internal.h
@@ -138,8 +138,18 @@
// one and sets |*out_bool| to resulting value. Otherwise, it returns zero.
int X509V3_bool_from_string(const char *str, ASN1_BOOLEAN *out_bool);
+// X509V3_get_value_bool decodes |value| as a boolean. On success, it returns
+// one and sets |*out_bool| to the resulting value. Otherwise, it returns zero.
int X509V3_get_value_bool(const CONF_VALUE *value, ASN1_BOOLEAN *out_bool);
+
+// X509V3_get_value_int decodes |value| as an integer. On success, it returns
+// one and sets |*aint| to the resulting value. Otherwise, it returns zero. If
+// |*aint| was non-NULL at the start of the function, it frees the previous
+// value before writing a new one.
int X509V3_get_value_int(const CONF_VALUE *value, ASN1_INTEGER **aint);
+
+// X509V3_get_section behaves like |NCONF_get_section| but queries |ctx|'s
+// config database.
const STACK_OF(CONF_VALUE) *X509V3_get_section(const X509V3_CTX *ctx,
const char *section);
diff --git a/crypto/x509v3/v3_utl.c b/crypto/x509v3/v3_utl.c
index 96ad229..c5bf823 100644
--- a/crypto/x509v3/v3_utl.c
+++ b/crypto/x509v3/v3_utl.c
@@ -337,6 +337,7 @@
X509V3_conf_err(value);
return 0;
}
+ ASN1_INTEGER_free(*aint);
*aint = itmp;
return 1;
}