update main-with-bazel from master branch
diff --git a/src/crypto/asn1/tasn_dec.c b/src/crypto/asn1/tasn_dec.c
index c5a6477..c45be7a 100644
--- a/src/crypto/asn1/tasn_dec.c
+++ b/src/crypto/asn1/tasn_dec.c
@@ -60,7 +60,6 @@
 #include <string.h>
 
 #include <openssl/asn1t.h>
-#include <openssl/buf.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
@@ -78,11 +77,6 @@
 static int asn1_check_eoc(const unsigned char **in, long len);
 static int asn1_find_end(const unsigned char **in, long len, char inf);
 
-static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,
-                        char inf, int tag, int aclass, int depth);
-
-static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen);
-
 static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
                            char *inf, char *cst,
                            const unsigned char **in, long len,
@@ -97,7 +91,7 @@
                                    const ASN1_TEMPLATE *tt, char opt,
                                    ASN1_TLC *ctx, int depth);
 static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
-                       int utype, char *free_cont, const ASN1_ITEM *it);
+                       int utype, const ASN1_ITEM *it);
 static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
                                  const unsigned char **in, long len,
                                  const ASN1_ITEM *it,
@@ -685,9 +679,8 @@
 {
     int ret = 0, utype;
     long plen;
-    char cst, inf, free_cont = 0;
+    char cst, inf;
     const unsigned char *p;
-    BUF_MEM buf = {0, NULL, 0 };
     const unsigned char *cont = NULL;
     long len;
     if (!pval) {
@@ -763,33 +756,11 @@
             p += plen;
         }
     } else if (cst) {
-        if (utype == V_ASN1_NULL || utype == V_ASN1_BOOLEAN
-            || utype == V_ASN1_OBJECT || utype == V_ASN1_INTEGER
-            || utype == V_ASN1_ENUMERATED) {
-            /* These types only have primitive encodings. */
-            OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_PRIMITIVE);
-            return 0;
-        }
-
-        /* Free any returned 'buf' content */
-        free_cont = 1;
-        /*
-         * Should really check the internal tags are correct but some things
-         * may get this wrong. The relevant specs say that constructed string
-         * types should be OCTET STRINGs internally irrespective of the type.
-         * So instead just check for UNIVERSAL class and ignore the tag.
-         */
-        if (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0)) {
-            goto err;
-        }
-        len = buf.length;
-        /* Append a final null to string */
-        if (!BUF_MEM_grow_clean(&buf, len + 1)) {
-            OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-            goto err;
-        }
-        buf.data[len] = 0;
-        cont = (const unsigned char *)buf.data;
+        /* This parser historically supported BER constructed strings. We no
+         * longer do and will gradually tighten this parser into a DER
+         * parser. BER types should use |CBS_asn1_ber_to_der|. */
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_PRIMITIVE);
+        return 0;
     } else {
         cont = p;
         len = plen;
@@ -797,22 +768,19 @@
     }
 
     /* We now have content length and type: translate into a structure */
-    /* asn1_ex_c2i may reuse allocated buffer, and so sets free_cont to 0 */
-    if (!asn1_ex_c2i(pval, cont, len, utype, &free_cont, it))
+    if (!asn1_ex_c2i(pval, cont, len, utype, it))
         goto err;
 
     *in = p;
     ret = 1;
  err:
-    if (free_cont && buf.data)
-        OPENSSL_free(buf.data);
     return ret;
 }
 
 /* Translate ASN1 content octets into a structure */
 
 static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
-                       int utype, char *free_cont, const ASN1_ITEM *it)
+                       int utype, const ASN1_ITEM *it)
 {
     ASN1_VALUE **opval = NULL;
     ASN1_STRING *stmp;
@@ -916,20 +884,11 @@
             stmp = (ASN1_STRING *)*pval;
             stmp->type = utype;
         }
-        /* If we've already allocated a buffer use it */
-        if (*free_cont) {
-            if (stmp->data)
-                OPENSSL_free(stmp->data);
-            stmp->data = (unsigned char *)cont; /* UGLY CAST! RL */
-            stmp->length = len;
-            *free_cont = 0;
-        } else {
-            if (!ASN1_STRING_set(stmp, cont, len)) {
-                OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-                ASN1_STRING_free(stmp);
-                *pval = NULL;
-                goto err;
-            }
+        if (!ASN1_STRING_set(stmp, cont, len)) {
+            OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+            ASN1_STRING_free(stmp);
+            *pval = NULL;
+            goto err;
         }
         break;
     }
@@ -1000,92 +959,6 @@
     return 1;
 }
 
-/*
- * This function collects the asn1 data from a constructred string type into
- * a buffer. The values of 'in' and 'len' should refer to the contents of the
- * constructed type and 'inf' should be set if it is indefinite length.
- */
-
-/*
- * This determines how many levels of recursion are permitted in ASN1 string
- * types. If it is not limited stack overflows can occur. If set to zero no
- * recursion is allowed at all. Although zero should be adequate examples
- * exist that require a value of 1. So 5 should be more than enough.
- */
-#define ASN1_MAX_STRING_NEST 5
-
-static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,
-                        char inf, int tag, int aclass, int depth)
-{
-    const unsigned char *p, *q;
-    long plen;
-    char cst, ininf;
-    p = *in;
-    inf &= 1;
-    /*
-     * If no buffer and not indefinite length constructed just pass over the
-     * encoded data
-     */
-    if (!buf && !inf) {
-        *in += len;
-        return 1;
-    }
-    while (len > 0) {
-        q = p;
-        /* Check for EOC */
-        if (asn1_check_eoc(&p, len)) {
-            /*
-             * EOC is illegal outside indefinite length constructed form
-             */
-            if (!inf) {
-                OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNEXPECTED_EOC);
-                return 0;
-            }
-            inf = 0;
-            break;
-        }
-
-        if (!asn1_check_tlen(&plen, NULL, NULL, &ininf, &cst, &p,
-                             len, tag, aclass, 0, NULL)) {
-            OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
-            return 0;
-        }
-
-        /* If indefinite length constructed update max length */
-        if (cst) {
-            if (depth >= ASN1_MAX_STRING_NEST) {
-                OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_STRING);
-                return 0;
-            }
-            if (!asn1_collect(buf, &p, plen, ininf, tag, aclass, depth + 1))
-                return 0;
-        } else if (plen && !collect_data(buf, &p, plen))
-            return 0;
-        len -= p - q;
-    }
-    if (inf) {
-        OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC);
-        return 0;
-    }
-    *in = p;
-    return 1;
-}
-
-static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen)
-{
-    int len;
-    if (buf) {
-        len = buf->length;
-        if (!BUF_MEM_grow_clean(buf, len + plen)) {
-            OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-            return 0;
-        }
-        OPENSSL_memcpy(buf->data + len, *p, plen);
-    }
-    *p += plen;
-    return 1;
-}
-
 /* Check for ASN1 EOC and swallow it if found */
 
 static int asn1_check_eoc(const unsigned char **in, long len)
diff --git a/src/crypto/bytestring/ber.c b/src/crypto/bytestring/ber.c
index df88432..fd35e97 100644
--- a/src/crypto/bytestring/ber.c
+++ b/src/crypto/bytestring/ber.c
@@ -30,6 +30,9 @@
 // ignores the constructed bit.
 static int is_string_type(unsigned tag) {
   switch (tag & ~CBS_ASN1_CONSTRUCTED) {
+    // TODO(davidben): Reject constructed BIT STRINGs. The current handling
+    // matches OpenSSL but is incorrect. See
+    // https://github.com/openssl/openssl/issues/12810.
     case CBS_ASN1_BITSTRING:
     case CBS_ASN1_OCTETSTRING:
     case CBS_ASN1_UTF8STRING:
diff --git a/src/crypto/x509/x509_test.cc b/src/crypto/x509/x509_test.cc
index 36d2a27..477e5a1 100644
--- a/src/crypto/x509/x509_test.cc
+++ b/src/crypto/x509/x509_test.cc
@@ -3463,3 +3463,38 @@
                X509_VERIFY_PARAM_clear_flags(param, X509_V_FLAG_TRUSTED_FIRST);
              }));
 }
+
+// kConstructedBitString is an X.509 certificate where the signature is encoded
+// as a BER constructed BIT STRING. Note that, while OpenSSL's parser accepts
+// this input, it interprets the value incorrectly.
+static const char kConstructedBitString[] = R"(
+-----BEGIN CERTIFICATE-----
+MIIBJTCBxqADAgECAgIE0jAKBggqhkjOPQQDAjAPMQ0wCwYDVQQDEwRUZXN0MCAX
+DTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAPMQ0wCwYDVQQDEwRUZXN0
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5itp4r9ln5e+Lx4NlIpM1Zdrt6ke
+DUb73ampHp3culoB59aXqAoY+cPEox5W4nyDSNsWGhz1HX7xlC1Lz3IiwaMQMA4w
+DAYDVR0TBAUwAwEB/zAKBggqhkjOPQQDAiNOAyQAMEYCIQCp0iIX5s30KXjihR4g
+KnJpd3seqGlVRqCVgrD0KGYDJgA1QAIhAKkx0vR82QU0NtHDD11KX/LuQF2T+2nX
+oeKp5LKAbMVi
+-----END CERTIFICATE-----
+)";
+
+// kConstructedOctetString is an X.509 certificate where an extension is encoded
+// as a BER constructed OCTET STRING.
+static const char kConstructedOctetString[] = R"(
+-----BEGIN CERTIFICATE-----
+MIIBJDCByqADAgECAgIE0jAKBggqhkjOPQQDAjAPMQ0wCwYDVQQDEwRUZXN0MCAX
+DTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAPMQ0wCwYDVQQDEwRUZXN0
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5itp4r9ln5e+Lx4NlIpM1Zdrt6ke
+DUb73ampHp3culoB59aXqAoY+cPEox5W4nyDSNsWGhz1HX7xlC1Lz3IiwaMUMBIw
+EAYDVR0TJAkEAzADAQQCAf8wCgYIKoZIzj0EAwIDSQAwRgIhAKnSIhfmzfQpeOKF
+HiAqcml3ex6oaVVGoJWCsPQoZjVAAiEAqTHS9HzZBTQ20cMPXUpf8u5AXZP7adeh
+4qnksoBsxWI=
+-----END CERTIFICATE-----
+)";
+
+TEST(X509Test, BER) {
+  // Constructed strings are forbidden in DER.
+  EXPECT_FALSE(CertFromPEM(kConstructedBitString));
+  EXPECT_FALSE(CertFromPEM(kConstructedOctetString));
+}