NativeEnumerated for OER, and tests

This commit is contained in:
Lev Walkin 2017-08-27 20:34:58 -07:00
parent 049a2d7da7
commit f9f3e06e21
7 changed files with 344 additions and 16 deletions

View File

@ -36,6 +36,7 @@ libasn1cskeletons_la_SOURCES = \
ISO646String.c ISO646String.h \
NULL.c NULL.h \
NativeEnumerated.c NativeEnumerated.h \
NativeEnumerated_oer.c \
NativeInteger.c NativeInteger.h \
NativeInteger_oer.c \
NativeReal.c NativeReal.h \

View File

@ -31,8 +31,8 @@ asn_TYPE_operation_t asn_OP_NativeEnumerated = {
0,
0,
#else
0,
0,
NativeEnumerated_decode_oer,
NativeEnumerated_encode_oer,
#endif /* ASN_DISABLE_OER_SUPPORT */
#ifdef ASN_DISABLE_PER_SUPPORT
0,

View File

@ -23,6 +23,8 @@ extern asn_TYPE_descriptor_t asn_DEF_NativeEnumerated;
extern asn_TYPE_operation_t asn_OP_NativeEnumerated;
xer_type_encoder_f NativeEnumerated_encode_xer;
oer_type_decoder_f NativeEnumerated_decode_oer;
oer_type_encoder_f NativeEnumerated_encode_oer;
per_type_decoder_f NativeEnumerated_decode_uper;
per_type_encoder_f NativeEnumerated_encode_uper;

View File

@ -0,0 +1,131 @@
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef ASN_DISABLE_OER_SUPPORT
#include <asn_internal.h>
#include <NativeEnumerated.h>
#include <errno.h>
asn_dec_rval_t
NativeEnumerated_decode_oer(asn_codec_ctx_t *opt_codec_ctx,
asn_TYPE_descriptor_t *td,
const asn_oer_constraints_t *constraints,
void **nint_ptr, const void *ptr, size_t size) {
asn_dec_rval_t rval = {RC_OK, 0};
long *native = (long *)*nint_ptr;
const uint8_t *b = ptr;
(void)opt_codec_ctx;
(void)constraints;
if(size < 1) {
ASN__DECODE_STARVED;
}
if((*b & 0x80) == 0) {
/*
* X.696 (08/2015) #11.2 Short form for Enumerated.
*/
if(!native) {
native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
if(!native) ASN__DECODE_FAILED;
}
*native = *b;
rval.consumed = 1;
} else {
/*
* X.696 (08/2015) #11.4 Long form for Enumerated.
*/
size_t length = *b & 0x7f;
const uint8_t *bend;
long value;
if(length < 1 || length > sizeof(*native)) {
ASN__DECODE_FAILED;
}
if((1 + length) > size) {
ASN__DECODE_STARVED;
}
b++;
bend = b + length;
value = (*b & 0x80) ? -1 : 0; /* Determine sign */
for(; b < bend; b++)
value = (value << 8) | *b;
if(value < 0) {
const asn_INTEGER_specifics_t *specs =
(const asn_INTEGER_specifics_t *)td->specifics;
if(specs && specs->field_unsigned) {
ASN__DECODE_FAILED;
}
}
if(!native) {
native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
if(!native) ASN__DECODE_FAILED;
}
*native = value;
rval.consumed = (1 + length);
}
return rval;
}
/*
* Encode as Canonical OER.
*/
asn_enc_rval_t
NativeEnumerated_encode_oer(asn_TYPE_descriptor_t *td,
const asn_oer_constraints_t *constraints,
void *sptr, asn_app_consume_bytes_f *cb,
void *app_key) {
asn_enc_rval_t er = {0, td, sptr};
long native;
(void)constraints;
if(!sptr) ASN__ENCODE_FAILED;
native = *(const long *)sptr;
if(native >= 0 && native <= 127) {
/* #11.2 Short form */
uint8_t b = native;
er.encoded = 1;
if(cb(&b, er.encoded, app_key) < 0) {
ASN__ENCODE_FAILED;
}
ASN__ENCODED_OK(er);
} else {
/* #11.2 Long form */
uint8_t buf[1 + sizeof(native)];
uint8_t *b = &buf[sizeof(native)]; /* Last addressable */
long final_pattern = -1 * (native < 0);
for(;;) {
*b-- = native;
native >>= 8;
if(native == final_pattern) {
if(final_pattern) {
if((b[1] & 0x80)) break;
} else {
if(!(b[1] & 0x80)) break;
}
}
}
*b = 0x80 | (&buf[sizeof(native)] - b);
er.encoded = 1 + (&buf[sizeof(native)] - b);
if(cb(b, er.encoded, app_key) < 0) {
ASN__ENCODE_FAILED;
}
ASN__ENCODED_OK(er);
}
}
#endif /* ASN_DISABLE_OER_SUPPORT */

View File

@ -75,6 +75,7 @@ OPEN_TYPE.h OPEN_TYPE_oer.c
INTEGER_oer.c
OCTET_STRING_oer.c
NativeInteger_oer.c
NativeEnumerated_oer.c
constr_SEQUENCE_oer.c
CODEC-PER: # THIS IS A SPECIAL SECTION

View File

@ -1,19 +1,20 @@
@CODE_COVERAGE_RULES@
check_PROGRAMS = \
check-ber_tlv_tag \
check-length \
check-OIDs \
check-GeneralizedTime \
check-OCTET_STRING \
check-UTF8String \
check-UTCTime \
check-INTEGER \
check-REAL \
check-XER \
check-OER-INTEGER \
check-PER \
check-PER-INTEGER
check_PROGRAMS = \
check-ber_tlv_tag \
check-length \
check-OIDs \
check-GeneralizedTime \
check-OCTET_STRING \
check-UTF8String \
check-UTCTime \
check-INTEGER \
check-REAL \
check-XER \
check-OER-INTEGER \
check-OER-NativeEnumerated \
check-PER \
check-PER-INTEGER
#Filter out the coverage options from CFLAGS as we don't need
#code coverage data for the tests executables

View File

@ -0,0 +1,192 @@
#include <stdio.h>
#include <assert.h>
#include <asn_codecs.h>
#include <NativeEnumerated.h>
#define CHECK_DECODE(code, a, b, c) check_decode(__LINE__, code, a, b, c)
#define CHECK_ROUNDTRIP(a) check_roundtrip(__LINE__, a);
static void
check_decode(int lineno, enum asn_dec_rval_code_e code, intmax_t control, const char *buf, size_t size) {
static char *code_s[] = { "RC_OK", "RC_WMORE", "RC_FAIL", "<error>" };
fprintf(stderr, "\n%d: OER decode (control %" PRIdMAX ")\n", lineno, control);
long value;
long *value_ptr = &value;
asn_dec_rval_t ret;
fprintf(stderr, "%d: buf[%zu]={%d, %d, ...}\n", lineno, size,
size <= 0 ? -1 : ((const uint8_t *)buf)[0],
size <= 1 ? -1 : ((const uint8_t *)buf)[1]);
ret = NativeEnumerated_decode_oer(NULL, &asn_DEF_NativeEnumerated, NULL,
(void **)&value_ptr, buf, size);
if(ret.code != RC_OK) {
/* Basic OER decode does not work */
fprintf(stderr, "%d: Failed oer_decode(ctl=%" PRIdMAX ", size=%zu)\n",
lineno, control, size);
if(ret.code == code) {
fprintf(stderr, " (That was expected)\n");
return;
} else {
fprintf(
stderr, " Unexpected return code %s (%d) expected %s\n",
code_s[(unsigned)ret.code <= RC_FAIL ? RC_FAIL : (RC_FAIL + 1)],
(int)ret.code, code_s[code]);
assert(ret.code == code);
}
} else {
intmax_t outcome = value;
if(outcome != control) {
/* Decoded value is wrong */
fprintf(stderr,
"%d: Decode result %" PRIdMAX " is not expected %" PRIdMAX
"\n",
lineno, outcome, control);
assert(outcome == control);
}
}
fprintf(stderr, "%d: Decode result %" PRIdMAX "\n", lineno, control);
}
static void
dump_data(int lineno, const uint8_t *buf, size_t size) {
const uint8_t *p = buf;
const uint8_t *end = buf + size;
fprintf(stderr, "%d: Encoded: [", lineno);
for(; p < end; p++) {
fprintf(stderr, "\\x%02x", *(const unsigned char *)p);
}
fprintf(stderr, "] (%zu bytes)\n", size);
}
static void
check_roundtrip(int lineno, intmax_t control) {
uint8_t tmpbuf[32];
size_t tmpbuf_size;
fprintf(stderr, "\n%d: OER round-trip value %" PRIdMAX "\n", lineno, control);
asn_enc_rval_t er;
asn_dec_rval_t ret;
long value_out = control;
long value_in = -42;
long *value_in_ptr = &value_in;
er = oer_encode_to_buffer(&asn_DEF_NativeEnumerated, NULL,
&value_out, tmpbuf, sizeof(tmpbuf));
if(er.encoded == -1) {
fprintf(stderr, "%d: OER encode failed for %s\n", lineno,
er.failed_type ? er.failed_type->name : "<none>");
assert(er.encoded != -1);
}
tmpbuf_size = er.encoded;
dump_data(lineno, tmpbuf, tmpbuf_size);
ret = asn_DEF_NativeEnumerated.op->oer_decoder(0, &asn_DEF_NativeEnumerated,
NULL, (void **)&value_in_ptr,
tmpbuf, tmpbuf_size);
if(ret.code != RC_OK) {
/* Basic OER decode does not work */
fprintf(stderr, "%d: Failed oer_decode(value=%" PRIdMAX ", size=%zu)\n",
lineno, control, tmpbuf_size);
assert(ret.code == 0);
} else {
intmax_t outcome = value_in;
if(outcome != control) {
/* Decoded value is wrong */
fprintf(stderr,
"%d: Decode result %" PRIdMAX " is not expected %" PRIdMAX
"\n",
lineno, outcome, control);
assert(outcome == control);
}
}
fprintf(stderr, "%d: Decode result %" PRIdMAX "\n", lineno, control);
}
int
main() {
CHECK_DECODE(RC_WMORE, 0, "", 0);
CHECK_DECODE(RC_OK, 0, "\x00", 1);
CHECK_DECODE(RC_FAIL, 0, "\x00", 1);
CHECK_DECODE(RC_WMORE, 0, "", 0);
CHECK_DECODE(RC_WMORE, 0, "", 0);
CHECK_DECODE(RC_OK, 0, "\x00", 1);
CHECK_DECODE(RC_OK, 0, "\x00", 1);
CHECK_DECODE(RC_OK, 0, "\x00", 1);
CHECK_DECODE(RC_OK, 1, "\x01", 1);
CHECK_DECODE(RC_FAIL, 0, "\xff", 1);
CHECK_DECODE(RC_FAIL, 0, "\x89", 1);
CHECK_DECODE(RC_WMORE, 0, "\x84", 1);
CHECK_DECODE(RC_WMORE, 0, "\x84\x00", 3);
CHECK_DECODE(RC_WMORE, 0, "\x84\x00\x00", 3);
CHECK_DECODE(RC_WMORE, 0, "\x84\x00\x00\x00", 4);
CHECK_DECODE(RC_OK, 0, "\x84\x00\x00\x00\x00", 5);
CHECK_DECODE(RC_OK, 1, "\x84\x00\x00\x00\x01", 5);
CHECK_DECODE(RC_OK, 127, "\x7f", 1);
CHECK_DECODE(RC_OK, 127, "\x81\x7f", 2);
CHECK_DECODE(RC_OK, 255, "\x82\x00\xff", 3);
CHECK_DECODE(RC_OK, -1, "\x81\xff", 2);
CHECK_DECODE(RC_OK, -1, "\x82\xff\xff", 3);
CHECK_DECODE(RC_OK, 1, "\x01\x00", 2);
CHECK_DECODE(RC_OK, 1, "\x01\x01", 2);
CHECK_DECODE(RC_OK, -1, "\x81\xff", 2);
CHECK_DECODE(RC_WMORE, -1, "\x82\x00\xff", 2);
CHECK_ROUNDTRIP(0);
CHECK_ROUNDTRIP(1);
CHECK_ROUNDTRIP(-1);
CHECK_ROUNDTRIP(-127);
CHECK_ROUNDTRIP(-128);
CHECK_ROUNDTRIP(-129);
CHECK_ROUNDTRIP(126);
CHECK_ROUNDTRIP(127);
CHECK_ROUNDTRIP(128);
CHECK_ROUNDTRIP(-65000);
CHECK_ROUNDTRIP(65000);
CHECK_ROUNDTRIP(65535);
CHECK_ROUNDTRIP(-65535);
CHECK_ROUNDTRIP(-65536);
CHECK_ROUNDTRIP(65536);
CHECK_ROUNDTRIP(32000);
for(size_t i = 0; i < 7 ; i++) {
intmax_t value = (intmax_t)1 << i;
CHECK_ROUNDTRIP(value);
value = -value;
CHECK_ROUNDTRIP(value);
}
for(size_t i = 0; i < 16 ; i++) {
intmax_t value = (intmax_t)1 << i;
CHECK_ROUNDTRIP(value);
value = -value;
CHECK_ROUNDTRIP(value);
}
for(size_t i = 0; i < 32 ; i++) {
intmax_t value = (intmax_t)1 << i;
CHECK_ROUNDTRIP(value);
value = -value;
CHECK_ROUNDTRIP(value);
}
for(size_t i = 0; i < 8 * sizeof(intmax_t) ; i++) {
intmax_t value = (intmax_t)1 << i;
CHECK_ROUNDTRIP(value);
value = -value;
CHECK_ROUNDTRIP(value);
}
}