summaryrefslogtreecommitdiff
path: root/epan/asn1.c
diff options
context:
space:
mode:
authorMaarten Bezemer <maarten.bezemer@gmail.com>2014-11-28 16:53:04 +0100
committerAnders Broman <a.broman58@gmail.com>2014-12-03 09:02:05 +0000
commit08c0247b78116dcfdba342222810697482108d3a (patch)
tree89ccc308a2c4fa3c2304c0b4970e6288f25d1051 /epan/asn1.c
parente55fe95c2a44e8889217c3160b5a120d210ced98 (diff)
downloadwireshark-08c0247b78116dcfdba342222810697482108d3a.tar.gz
Support dissecting REAL (BER) data values
Both exponent and 'integer N' values are limited: * max exponent is 3 octets/24-bits * max integer N is 8 octets/64-bit Tested with zero value/length, integers, doubles, positive and negative numbers all using the Basic Encoding Rules (BER) Change-Id: If92e1b3e209c42909b8cb76e6f50b8e6cd1da0da Reviewed-on: https://code.wireshark.org/review/5527 Reviewed-by: Michael Mann <mmann78@netscape.net> Petri-Dish: Michael Mann <mmann78@netscape.net> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan/asn1.c')
-rw-r--r--epan/asn1.c73
1 files changed, 69 insertions, 4 deletions
diff --git a/epan/asn1.c b/epan/asn1.c
index 1ce1bdcb47..b878c719b8 100644
--- a/epan/asn1.c
+++ b/epan/asn1.c
@@ -196,24 +196,89 @@ rose_ctx_t *get_rose_ctx(void *ptr) {
return rctx;
}
-double asn1_get_real(const guint8 *real_ptr, gint real_len) {
+/** Only tested for BER */
+double asn1_get_real(const guint8 *real_ptr, gint len) {
guint8 octet;
const guint8 *p;
guint8 *buf;
double val = 0;
- if (real_len < 1) return val;
+ /* 8.5.2 If the real value is the value zero,
+ * there shall be no contents octets in the encoding.
+ */
+ if (len < 1) return val;
+
octet = real_ptr[0];
p = real_ptr + 1;
- real_len -= 1;
+ len -= 1;
if (octet & 0x80) { /* binary encoding */
+ int i;
+ gboolean Eneg;
+ gint8 S; /* Sign */
+ guint8 B; /* Base */
+ guint8 F; /* scaling Factor */
+ gint32 E = 0; /* Exponent (supported max 3 octets/24 bit) */
+ guint64 N = 0; /* N (supported max 8 octets/64 bit) */
+
+ guint8 lenE, lenN;
+
+ if(octet & 0x40) S = -1; else S = 1;
+ switch(octet & 0x30) {
+ case 0x00: B = 2; break;
+ case 0x10: B = 8; break;
+ case 0x20: B = 16; break;
+ case 0x30: /* Reserved */
+ default:
+ /* TODO Add some warning in tree about reserved value for Base */
+ return 0;
+ }
+ F = (octet & 0x0c) >> 2;
+
+ /* 8.5.6.4 Exponent length */
+ lenE = (octet & 0x3) + 1;
+ if(lenE == 4)
+ {
+ /* we can't handle exponents > 24 bits */
+ /* TODO Next octet(s) define length of exponent */
+ DISSECTOR_ASSERT_NOT_REACHED();
+ }
+
+ Eneg = (*p) & 0x80 ? TRUE : FALSE;
+ for (i = 0; i < lenE; i++) {
+ if(Eneg) {
+ /* 2's complement: inverse bits */
+ E = (E<<8) | ((guint8) ~(*p));
+ } else {
+ E = (E<<8) | *p;
+ }
+ p++;
+ }
+ if(Eneg) {
+ /* 2's complement: ... and add 1 (and make negative of course) */
+ E = -(E + 1);
+ }
+
+ lenN = len - lenE;
+ if(lenN > 8)
+ {
+ /* we can't handle integers > 64 bits */
+ DISSECTOR_ASSERT_NOT_REACHED();
+ }
+ for (i=0; i<lenN; i++) {
+ N = (N<<8) | *p;
+ p++;
+ }
+ val = (double) S * N * pow(2, F) * pow(B, E);
+#ifdef DEBUG
+ printf("S = %d, N = %lu, F = %u, B = %u, E = %d -> %f\n", S, N, F, B, E, Eneg, val);
+#endif
} else if (octet & 0x40) { /* SpecialRealValue */
switch (octet & 0x3F) {
case 0x00: val = HUGE_VAL; break;
case 0x01: val = -HUGE_VAL; break;
}
} else { /* decimal encoding */
- buf = ep_strndup(p, real_len);
+ buf = ep_strndup(p, len);
val = atof(buf);
}