Commit 5fe72e9d authored by Lev Walkin's avatar Lev Walkin

test encoding of special values

parent 833d2752
...@@ -577,14 +577,14 @@ asn_double2REAL(REAL_t *st, double dbl_value) { ...@@ -577,14 +577,14 @@ asn_double2REAL(REAL_t *st, double dbl_value) {
st->buf[1] = 0; st->buf[1] = 0;
st->size = 1; st->size = 1;
} else { } else {
if(copysign(1.0, dbl_value) < 0.0) { if(copysign(1.0, dbl_value) >= 0.0) {
st->buf[0] = 0x80 | 0x40;
st->buf[1] = 0;
st->size = 2;
} else {
/* no content octets: positive zero */ /* no content octets: positive zero */
st->buf[0] = 0; /* JIC */ st->buf[0] = 0; /* JIC */
st->size = 0; st->size = 0;
} else {
/* Negative zero. #8.5.3, 8.5.9 */
st->buf[0] = 0x43;
st->size = 1;
} }
} }
return 0; return 0;
......
...@@ -39,26 +39,29 @@ d2s(double d, int canonical, const char *str) { ...@@ -39,26 +39,29 @@ d2s(double d, int canonical, const char *str) {
* is as given in the (sample) and (canonical_sample) arguments. * is as given in the (sample) and (canonical_sample) arguments.
*/ */
static void static void
check_str_repr(double d, const char *sample, const char *canonical_sample) { check_str_representation(double d, const char *sample, const char *canonical_sample) {
char *s0, *s1; char *s0, *s1;
s0 = d2s(d, 0, sample); s0 = d2s(d, 0, sample);
s1 = d2s(d, 1, canonical_sample); s1 = d2s(d, 1, canonical_sample);
if(sample) { if(sample) {
printf("Checking %f->[%s] against [%s]%s\n", printf("Checking %f->[\"%s\"] against [\"%s\"]%s\n",
d, s0, sample, d, s0, sample,
canonical_sample ? " (canonical follows...)" : "" canonical_sample ? " (canonical follows...)" : ""
); );
assert(!strcmp(s0, sample)); assert(!strcmp(s0, sample));
} }
if(canonical_sample) { if(canonical_sample) {
printf("Checking %f->[%s] against [%s] (canonical)\n", printf("Checking %f->[\"%s\"] against [\"%s\"] (canonical)\n",
d, s1, canonical_sample); d, s1, canonical_sample);
assert(!strcmp(s1, canonical_sample)); assert(!strcmp(s1, canonical_sample));
} }
} }
#define check(rn, d, str1, str2) \
check_impl(rn, d, str1, str2, __LINE__)
static void static void
check_impl(REAL_t *rn, double orig_dbl, const char *sample, const char *canonical_sample, int line) { check_impl(REAL_t *rn, double orig_dbl, const char *sample, const char *canonical_sample, int line) {
double val; double val;
...@@ -96,57 +99,8 @@ check_impl(REAL_t *rn, double orig_dbl, const char *sample, const char *canonica ...@@ -96,57 +99,8 @@ check_impl(REAL_t *rn, double orig_dbl, const char *sample, const char *canonica
assert((isnan(orig_dbl) && isnan(val)) || val == orig_dbl); assert((isnan(orig_dbl) && isnan(val)) || val == orig_dbl);
printf("OK\n"); printf("OK\n");
check_str_repr(val, sample, canonical_sample); check_str_representation(val, sample, canonical_sample);
}
uint8_t buf_1_0[] = { 0x80, 0xcc, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t buf_1_1[] = { 0x80, 0xcc, 0x11, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a };
uint8_t buf_3_14[] = { 0x80, 0xcd, 0x19, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f };
/* These ones are very interesting! They check mantissa overflow! */
uint8_t buf_mo1[] = { 0xC0, 0xc5, 0x19, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,3};
uint8_t buf_mo2[] = { 0x80, 0xbd, 0x19, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,3,2};
static void
check_buf(uint8_t *buf, size_t bufsize, double verify, const char *sample, const char *canonical_sample) {
REAL_t rn;
double val;
uint8_t *p, *end;
int ret;
printf("verify double value %.12f [", verify);
for(p = (uint8_t *)&verify, end = p + sizeof(double); p < end ; p++)
printf("%02x", *p);
printf("] (ilogb %d)\n", ilogb(verify));
rn.buf = 0;
rn.size = 0;
ret = asn_double2REAL(&rn, verify);
assert(ret == 0);
printf("canonical DER: [");
for(p = rn.buf, end = p + rn.size; p < end; p++)
printf("%02x", *p);
printf("]\n");
rn.buf = buf;
rn.size = bufsize;
printf("received as: [");
for(p = rn.buf, end = p + rn.size; p < end; p++)
printf("%02x", *p);
printf("]\n");
ret = asn_REAL2double(&rn, &val);
assert(ret == 0);
printf("%.12f vs %.12f\n", verify, val);
assert(val == verify);
check_str_repr(val, sample, canonical_sample);
} }
static void static void
check_xer(int fuzzy, double orig_value) { check_xer(int fuzzy, double orig_value) {
asn_enc_rval_t er; asn_enc_rval_t er;
...@@ -207,16 +161,167 @@ check_xer(int fuzzy, double orig_value) { ...@@ -207,16 +161,167 @@ check_xer(int fuzzy, double orig_value) {
assert(memcmp(newst1->buf, st.buf, st.size) == 0); assert(memcmp(newst1->buf, st.buf, st.size) == 0);
} }
#define check(rn, d, str1, str2) \ static void
check_impl(rn, d, str1, str2, __LINE__) check_ber_buffer_twoway(double d, const char *sample, const char *canonical_sample, uint8_t *inbuf, size_t insize, uint8_t *outbuf, size_t outsize) {
REAL_t rn;
double val;
int ret;
/*
* Decode our expected buffer and check that it matches the given (d).
*/
rn.buf = inbuf;
rn.size = insize;
asn_REAL2double(&rn, &val);
if(isnan(val)) assert(isnan(d));
if(isnan(d)) assert(isnan(val));
if(!isnan(val) && !isnan(d)) {
assert(copysign(1.0, d) == copysign(1.0, val));
assert(d == val);
}
/*
* Encode value and check that it matches our expected buffer.
*/
memset(&rn, 0, sizeof(rn));
ret = asn_double2REAL(&rn, d);
assert(ret == 0);
uint8_t *p, *end;
printf("received as: [");
for(p = rn.buf, end = p + rn.size; p < end; p++)
printf("%02x", *p);
printf("]\n");
printf("received as: [");
for(p = outbuf, end = p + outsize; p < end; p++)
printf("%02x", *p);
printf("]\n");
if(rn.size != outsize) {
printf("Encoded %f into %d expected %ld\n",
d, (int)rn.size, outsize);
assert(rn.size == outsize);
}
assert(memcmp(rn.buf, outbuf, rn.size) == 0);
check_str_representation(d, sample, canonical_sample);
}
static void
check_ber_buffer_oneway(double d, const char *sample, const char *canonical_sample, uint8_t *buf, size_t bufsize) {
REAL_t rn;
double val;
uint8_t *p, *end;
int ret;
memset(&rn, 0, sizeof(rn));
printf("verify double value %.12f [", d);
for(p = (uint8_t *)&d, end = p + sizeof(double); p < end ; p++)
printf("%02x", *p);
printf("] (ilogb %d)\n", ilogb(d));
ret = asn_double2REAL(&rn, d);
assert(ret == 0);
printf("canonical DER: [");
for(p = rn.buf, end = p + rn.size; p < end; p++)
printf("%02x", *p);
printf("]\n");
rn.buf = buf;
rn.size = bufsize;
printf("received as: [");
for(p = rn.buf, end = p + rn.size; p < end; p++)
printf("%02x", *p);
printf("]\n");
ret = asn_REAL2double(&rn, &val);
assert(ret == 0);
printf("%.12f vs %.12f\n", d, val);
assert(val == d);
check_str_representation(val, sample, canonical_sample);
}
static void
check_ber_encoding() {
static const double zero = 0.0;
#define CHECK_BER_STRICT(v, nocan, can, inbuf, outbuf) \
check_ber_buffer_twoway(v, nocan, can, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf))
#define CHECK_BER_NONSTRICT(v, nocan, can, buf) \
check_ber_buffer_oneway(v, nocan, can, buf, sizeof(buf))
/*
* X.690 8.4 Encoding of an enumerated value.
*/
/* 8.5.2 If the real value is the value plus zero,
* there shall be no contents octet in the encoding */
{ uint8_t b_0[] = {};
CHECK_BER_STRICT(0, "0", "0", b_0, b_0);
}
/* 8.5.3 When -0 is to be encoded, there shall be only one contents octet */
{ uint8_t b_m0[] = { 0x43 };
CHECK_BER_STRICT(-0.0, "-0", "-0", b_m0, b_m0);
}
/* Old way of encoding -0.0: 8.5.6 a) */
{ uint8_t b_m0[] = { 0x43 };
uint8_t b_m0_856a[] = { 0xC0, 0x00 }; /* #8.5.6 a) */
uint8_t b_m0_856a_1[] = { 0xC0, 0x00, 0x00 };
uint8_t b_m0_856a_2[] = { 0xC0, 0x00, 0x00, 0x00 };
uint8_t b_m0_856a_3[] = { 0xC0, 0x00, 0x00, 0x00, 0x00 };
CHECK_BER_STRICT(-0.0, "-0", "-0", b_m0_856a, b_m0);
CHECK_BER_STRICT(-0.0, "-0", "-0", b_m0_856a_1, b_m0);
CHECK_BER_STRICT(-0.0, "-0", "-0", b_m0_856a_2, b_m0);
CHECK_BER_STRICT(-0.0, "-0", "-0", b_m0_856a_3, b_m0);
}
/* 8.5.6 c) => 8.5.9 SpecialRealValue */
{ uint8_t b_pinf[] = { 0x40 };
uint8_t b_minf[] = { 0x41 };
uint8_t b_nan[] = { 0x42 };
CHECK_BER_STRICT(1.0/zero, "<PLUS-INFINITY/>", "<PLUS-INFINITY/>", b_pinf, b_pinf);
CHECK_BER_STRICT(-1.0/zero, "<MINUS-INFINITY/>", "<MINUS-INFINITY/>", b_minf, b_minf);
CHECK_BER_STRICT(zero/zero, "<NOT-A-NUMBER/>", "<NOT-A-NUMBER/>", b_nan, b_nan);
}
{
uint8_t b_1_0[] =
{ 0x80, 0xcc, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t b_1_1[] =
{ 0x80, 0xcc, 0x11, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a };
uint8_t b_3_14[] =
{ 0x80, 0xcd, 0x19, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f };
uint8_t b_3_14_mo1[] =
{ 0xC0, 0xc5, 0x19, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,3};
uint8_t b_3_14_mo2[] =
{ 0x80, 0xbd, 0x19, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,3,2};
CHECK_BER_NONSTRICT(1.0, "1.0", "1.0E0", b_1_0);
CHECK_BER_NONSTRICT(1.1, "1.1", "1.1E0", b_1_1);
CHECK_BER_NONSTRICT(3.14, "3.14", "3.14E0", b_3_14);
/* These two are very interesting! They check mantissa overflow! */
CHECK_BER_NONSTRICT(-3.14, "-3.14", "-3.14E0", b_3_14_mo1);
CHECK_BER_NONSTRICT(3.14, "3.14", "3.14E0", b_3_14_mo2);
}
}
int int
main() { main() {
REAL_t rn; REAL_t rn;
static const double zero = 0.0; static const double zero = 0.0;
memset(&rn, 0, sizeof(rn)); memset(&rn, 0, sizeof(rn));
check_ber_encoding();
check(&rn, 0.0, "0", "0"); check(&rn, 0.0, "0", "0");
check(&rn, -0.0, "-0", "-0"); /* minus-zero */ check(&rn, -0.0, "-0", "-0"); /* minus-zero */
check(&rn, zero/zero, "<NOT-A-NUMBER/>", "<NOT-A-NUMBER/>"); check(&rn, zero/zero, "<NOT-A-NUMBER/>", "<NOT-A-NUMBER/>");
...@@ -260,12 +365,6 @@ main() { ...@@ -260,12 +365,6 @@ main() {
check(&rn, 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000033333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333, 0, 0); check(&rn, 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000033333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333, 0, 0);
check(&rn, -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, 0, 0); check(&rn, -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, 0, 0);
check_buf(buf_1_0, sizeof(buf_1_0), 1.0, "1.0", "1.0E0");
check_buf(buf_1_1, sizeof(buf_1_1), 1.1, "1.1", "1.1E0");
check_buf(buf_3_14, sizeof(buf_3_14), 3.14, "3.14", "3.14E0");
check_buf(buf_mo1, sizeof(buf_mo1), -3.14, "-3.14", "-3.14E0");
check_buf(buf_mo2, sizeof(buf_mo2), 3.14, "3.14", "3.14E0");
#ifdef NAN #ifdef NAN
check_xer(0, NAN); /* "<NOT-A-NUMBER/>" */ check_xer(0, NAN); /* "<NOT-A-NUMBER/>" */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment