Fix decoding of REAL values in NR3.

The NR3 form of values is used by Erlang to communicate REAL data.
aper
Lev Walkin 2011-06-25 15:48:52 -07:00
parent cf6c1e2302
commit 0959ffb20c
3 changed files with 48 additions and 8 deletions

View File

@ -9,6 +9,7 @@
* PER encoding correctness fix. (Severity: high; Security impact: low)
Reported by Grzegorz Aksamit.
* ENUMERATED extension values check relaxed. Reported by Gabriel Burca.
* Fixed decimal decoding of REAL values in -fnative-types mode (Severity: medium; Security impact: medium)
0.9.22: 2008-Nov-19

View File

@ -107,10 +107,39 @@ NativeReal_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
tmp.buf = (uint8_t *)unconst_buf.nonconstbuf;
tmp.size = length;
if(asn_REAL2double(&tmp, &d)) {
rval.code = RC_FAIL;
rval.consumed = 0;
return rval;
if(length < (ber_tlv_len_t)size) {
int ret;
uint8_t saved_byte = tmp.buf[tmp.size];
tmp.buf[tmp.size] = '\0';
ret = asn_REAL2double(&tmp, &d);
tmp.buf[tmp.size] = saved_byte;
if(ret) {
rval.code = RC_FAIL;
rval.consumed = 0;
return rval;
}
} else if(length < 48 /* Enough for longish %f value. */) {
tmp.buf = alloca(length + 1);
tmp.size = length;
memcpy(tmp.buf, buf_ptr, length);
tmp.buf[tmp.size] = '\0';
if(asn_REAL2double(&tmp, &d)) {
rval.code = RC_FAIL;
rval.consumed = 0;
return rval;
}
} else {
/* This should probably never happen: impractically long value */
tmp.buf = CALLOC(1, length + 1);
tmp.size = length;
if(tmp.buf) memcpy(tmp.buf, buf_ptr, length);
if(!tmp.buf || asn_REAL2double(&tmp, &d)) {
FREEMEM(tmp.buf);
rval.code = RC_FAIL;
rval.consumed = 0;
return rval;
}
FREEMEM(tmp.buf);
}
*Dbl = d;

View File

@ -403,21 +403,31 @@ asn_REAL2double(const REAL_t *st, double *dbl_value) {
errno = EINVAL;
return -1;
case 0x00: { /* X.690: 8.5.6 */
case 0x00: { /* X.690: 8.5.7 */
/*
* Decimal. NR{1,2,3} format.
*/
double d;
assert(st->buf[st->size - 1] == 0); /* Security, vashu mat' */
if(octv == 0 || octv & 0x3C == 0) {
/* Remaining values of bits 6 to 1 are Reserved. */
errno = EINVAL;
return -1;
}
d = strtod((char *)st->buf, 0);
if(st->buf[st->size]) {
/* By contract, an input buffer should be null-terminated */
errno = EINVAL;
return -1;
}
d = strtod((char *)&st->buf[1], 0);
if(finite(d)) {
*dbl_value = d;
return 0;
} else {
errno = ERANGE;
return 0;
return -1;
}
}
}