Fix decoding of REAL values in NR3.
The NR3 form of values is used by Erlang to communicate REAL data.
diff --git a/ChangeLog b/ChangeLog
index dc8d2b7..d7a9d78 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 a1ff91e..605ecb0 100644
--- a/skeletons/NativeReal.c
+++ b/skeletons/NativeReal.c
@@ -107,10 +107,39 @@
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 5e93ac8..6411aa4 100644
--- a/skeletons/REAL.c
+++ b/skeletons/REAL.c
@@ -403,21 +403,31 @@
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;
}
}
}