diff --git a/ChangeLog b/ChangeLog index dc8d2b72..d7a9d784 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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 diff --git a/skeletons/NativeReal.c b/skeletons/NativeReal.c index a1ff91e1..605ecb05 100644 --- a/skeletons/NativeReal.c +++ b/skeletons/NativeReal.c @@ -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; diff --git a/skeletons/REAL.c b/skeletons/REAL.c index 5e93ac8a..6411aa4a 100644 --- a/skeletons/REAL.c +++ b/skeletons/REAL.c @@ -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; } } }