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;
 		}
 	  }
 	}