141 |
|
#endif |
142 |
|
|
143 |
|
#define HEADER_SIZE 8 |
144 |
+ |
#define ASN1_CHUNK_INITIAL_SIZE (16 * 1024) |
145 |
|
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) |
146 |
|
{ |
147 |
|
BUF_MEM *b; |
218 |
|
/* suck in c.slen bytes of data */ |
219 |
|
want = c.slen; |
220 |
|
if (want > (len - off)) { |
221 |
+ |
size_t chunk_max = ASN1_CHUNK_INITIAL_SIZE; |
222 |
+ |
|
223 |
|
want -= (len - off); |
224 |
|
if (want > INT_MAX /* BIO_read takes an int length */ || |
225 |
|
len + want < len) { |
226 |
|
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); |
227 |
|
goto err; |
228 |
|
} |
226 |
– |
if (!BUF_MEM_grow_clean(b, len + want)) { |
227 |
– |
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE); |
228 |
– |
goto err; |
229 |
– |
} |
229 |
|
while (want > 0) { |
230 |
< |
i = BIO_read(in, &(b->data[len]), want); |
231 |
< |
if (i <= 0) { |
232 |
< |
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, |
233 |
< |
ASN1_R_NOT_ENOUGH_DATA); |
230 |
> |
/* |
231 |
> |
* Read content in chunks of increasing size |
232 |
> |
* so we can return an error for EOF without |
233 |
> |
* having to allocate the entire content length |
234 |
> |
* in one go. |
235 |
> |
*/ |
236 |
> |
size_t chunk = want > chunk_max ? chunk_max : want; |
237 |
> |
|
238 |
> |
if (!BUF_MEM_grow_clean(b, len + chunk)) { |
239 |
> |
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE); |
240 |
|
goto err; |
241 |
|
} |
242 |
+ |
want -= chunk; |
243 |
+ |
while (chunk > 0) { |
244 |
+ |
i = BIO_read(in, &(b->data[len]), chunk); |
245 |
+ |
if (i <= 0) { |
246 |
+ |
ASN1err(ASN1_F_ASN1_D2I_READ_BIO, |
247 |
+ |
ASN1_R_NOT_ENOUGH_DATA); |
248 |
+ |
goto err; |
249 |
+ |
} |
250 |
|
/* |
251 |
|
* This can't overflow because |len+want| didn't |
252 |
|
* overflow. |
253 |
|
*/ |
254 |
< |
len += i; |
255 |
< |
want -= i; |
254 |
> |
len += i; |
255 |
> |
chunk -= i; |
256 |
> |
} |
257 |
> |
if (chunk_max < INT_MAX/2) |
258 |
> |
chunk_max *= 2; |
259 |
|
} |
260 |
|
} |
261 |
|
if (off + c.slen < off) { |