}
#endif
-#define HEADER_SIZE 8
+#define HEADER_SIZE 2
#define ASN1_CHUNK_INITIAL_SIZE (16 * 1024)
int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
{
}
i = BIO_read(in, &(b->data[len]), (int)want);
- if (i <= 0 && diff == 0) {
+ if (i <= 0) {
ERR_raise(ERR_LIB_ASN1, ASN1_R_NOT_ENOUGH_DATA);
goto err;
}
}
/* else data already loaded */
+ /* make sure there is enough data for a complete header */
p = (unsigned char *)&(b->data[off]);
q = p;
diff = len - off;
- if (diff == 0)
+ if (diff < 2) {
+ /* Failed sanity check */
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_NOT_ENOUGH_DATA);
goto err;
+ }
+
+ diff--;
+ if ((*(q++) & V_ASN1_PRIMITIVE_TAG) == V_ASN1_PRIMITIVE_TAG) {
+ /* Multi-byte tag. See if we have the whole thing yet */
+ do {
+ diff--;
+ } while (diff > 0 && *(q++) & 0x80);
+
+ if (diff == 0) {
+ /*
+ * End of current data, will need at least 1 more byte for
+ * length. 2 if the tag is still incomplete
+ */
+ want = q - p + 2;
+ if (*q & 0x80) {
+ want++;
+ }
+ continue;
+ }
+ }
+
+ /* Check the length. This should also work for indefinite length */
+ diff--;
+ if (*q & 0x80) {
+ unsigned int i = *q & 0x7f;
+
+ if (i > sizeof(long)) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG);
+ goto err;
+ }
+ if (i > diff) {
+ want = q - p + i + 1;
+ continue;
+ }
+ }
+
+ /*
+ * We have a complete header now, assuming we didn't hit EOF. Parse the
+ * tag and length
+ */
+ q = p;
+ diff = len - off;
inf = ASN1_get_object(&q, &slen, &tag, &xclass, (int)diff);
if (inf & 0x80) {
unsigned long e;