mirror of https://gerrit.osmocom.org/asn1c
XER can decode long values
This commit is contained in:
parent
55f106a8b2
commit
c744a02926
|
@ -3,14 +3,14 @@
|
|||
|
||||
* skeletons/standard-modules directory is now used for standard types.
|
||||
* Fixed class field access problem (Test case 98)
|
||||
(Severity: medim; Security impact: none)
|
||||
(Severity: medium; Security impact: none)
|
||||
* Refactored Information Object Classes parsing.
|
||||
* Refactored Parameterization support.
|
||||
* [typedef enum foo {}] foo_e; is now e_foo, see #1287989
|
||||
* Refactored ValueSetTypeAssignment parsing.
|
||||
* First release of PER encoder (does not encode SETs yet).
|
||||
* asn-decoder-template.c renamed into converter-sample.c
|
||||
* MEGACO (Media Gateway Control Protocol) decoder sample added.
|
||||
* First release of PER encoder (does not encode SETs yet).
|
||||
|
||||
0.9.20: 2006-Mar-06
|
||||
|
||||
|
|
|
@ -35,6 +35,19 @@ cat Makefile.am.sample \
|
|||
echo " @touch ${ASN1PDU}.c"
|
||||
echo " make"
|
||||
echo
|
||||
echo 'check: ${TARGET}'
|
||||
echo " @if test -f ./sample-${ASN1PDU}-1.[db]er ; then \\"
|
||||
echo " for f in ./sample-${ASN1PDU}-*.[db]er; do \\"
|
||||
echo ' echo "Recoding $$f into XER and back..."; \'
|
||||
echo ' ./${TARGET} -iber -oxer $$f > ./.tmp.1.$$ || exit 2; \'
|
||||
echo ' ./${TARGET} -ixer -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \'
|
||||
echo ' diff ./.tmp.1.$$ ./.tmp.2.$$ || exit 2; \'
|
||||
echo ' rm -f ./.tmp.[12].$$; \'
|
||||
echo ' done; fi'
|
||||
echo ' @echo ================'
|
||||
echo ' @echo All tests passed'
|
||||
echo ' @echo ================'
|
||||
echo
|
||||
echo "distclean: clean"
|
||||
echo ' rm -f $(ASN_MODULE_SOURCES) $(ASN_MODULE_HEADERS)'
|
||||
echo ' rm -f $(ASN_CONVERTER_SOURCES) $(ASN_CONVERTER_HEADERS)'
|
||||
|
|
|
@ -196,6 +196,19 @@ LDAPMessage.c: ../sample.makefile.regen
|
|||
@touch LDAPMessage.c
|
||||
make
|
||||
|
||||
check: ${TARGET}
|
||||
@if test -f ./sample-LDAPMessage-1.[db]er ; then \
|
||||
for f in ./sample-LDAPMessage-*.[db]er; do \
|
||||
echo "Recoding $$f into XER and back..."; \
|
||||
./${TARGET} -iber -oxer $$f > ./.tmp.1.$$ || exit 2; \
|
||||
./${TARGET} -ixer -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \
|
||||
diff ./.tmp.1.$$ ./.tmp.2.$$ || exit 2; \
|
||||
rm -f ./.tmp.[12].$$; \
|
||||
done; fi
|
||||
@echo ================
|
||||
@echo All tests passed
|
||||
@echo ================
|
||||
|
||||
distclean: clean
|
||||
rm -f $(ASN_MODULE_SOURCES) $(ASN_MODULE_HEADERS)
|
||||
rm -f $(ASN_CONVERTER_SOURCES) $(ASN_CONVERTER_HEADERS)
|
||||
|
|
|
@ -318,6 +318,19 @@ MegacoMessage.c: ../sample.makefile.regen
|
|||
@touch MegacoMessage.c
|
||||
make
|
||||
|
||||
check: ${TARGET}
|
||||
@if test -f ./sample-MegacoMessage-1.[db]er ; then \
|
||||
for f in ./sample-MegacoMessage-*.[db]er; do \
|
||||
echo "Recoding $$f into XER and back..."; \
|
||||
./${TARGET} -iber -oxer $$f > ./.tmp.1.$$ || exit 2; \
|
||||
./${TARGET} -ixer -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \
|
||||
diff ./.tmp.1.$$ ./.tmp.2.$$ || exit 2; \
|
||||
rm -f ./.tmp.[12].$$; \
|
||||
done; fi
|
||||
@echo ================
|
||||
@echo All tests passed
|
||||
@echo ================
|
||||
|
||||
distclean: clean
|
||||
rm -f $(ASN_MODULE_SOURCES) $(ASN_MODULE_HEADERS)
|
||||
rm -f $(ASN_CONVERTER_SOURCES) $(ASN_CONVERTER_HEADERS)
|
||||
|
|
|
@ -378,6 +378,19 @@ Certificate.c: ../sample.makefile.regen
|
|||
@touch Certificate.c
|
||||
make
|
||||
|
||||
check: ${TARGET}
|
||||
@if test -f ./sample-Certificate-1.[db]er ; then \
|
||||
for f in ./sample-Certificate-*.[db]er; do \
|
||||
echo "Recoding $$f into XER and back..."; \
|
||||
./${TARGET} -iber -oxer $$f > ./.tmp.1.$$ || exit 2; \
|
||||
./${TARGET} -ixer -oxer ./.tmp.1.$$ > ./.tmp.2.$$ || exit 2; \
|
||||
diff ./.tmp.1.$$ ./.tmp.2.$$ || exit 2; \
|
||||
rm -f ./.tmp.[12].$$; \
|
||||
done; fi
|
||||
@echo ================
|
||||
@echo All tests passed
|
||||
@echo ================
|
||||
|
||||
distclean: clean
|
||||
rm -f $(ASN_MODULE_SOURCES) $(ASN_MODULE_HEADERS)
|
||||
rm -f $(ASN_CONVERTER_SOURCES) $(ASN_CONVERTER_HEADERS)
|
||||
|
|
|
@ -297,6 +297,20 @@ INTEGER_map_value2enum(asn_INTEGER_specifics_t *specs, long value) {
|
|||
INTEGER__compar_value2enum);
|
||||
}
|
||||
|
||||
static int
|
||||
INTEGER_st_prealloc(INTEGER_t *st, int min_size) {
|
||||
void *p = MALLOC(min_size + 1);
|
||||
if(p) {
|
||||
void *b = st->buf;
|
||||
st->size = 0;
|
||||
st->buf = p;
|
||||
FREEMEM(b);
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode the chunk of XML text encoding INTEGER.
|
||||
*/
|
||||
|
@ -310,11 +324,19 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun
|
|||
const char *lstop = lstart + chunk_size;
|
||||
enum {
|
||||
ST_SKIPSPACE,
|
||||
ST_SKIPSPHEX,
|
||||
ST_WAITDIGITS,
|
||||
ST_DIGITS,
|
||||
ST_HEXDIGIT1,
|
||||
ST_HEXDIGIT2,
|
||||
ST_HEXCOLON,
|
||||
ST_EXTRASTUFF
|
||||
} state = ST_SKIPSPACE;
|
||||
|
||||
if(chunk_size)
|
||||
ASN_DEBUG("INTEGER body %d 0x%2x..0x%2x",
|
||||
chunk_size, *lstart, lstop[-1]);
|
||||
|
||||
/*
|
||||
* We may have received a tag here. It will be processed inline.
|
||||
* Use strtoul()-like code and serialize the result.
|
||||
|
@ -323,7 +345,19 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun
|
|||
int lv = *lp;
|
||||
switch(lv) {
|
||||
case 0x09: case 0x0a: case 0x0d: case 0x20:
|
||||
if(state == ST_SKIPSPACE) continue;
|
||||
switch(state) {
|
||||
case ST_SKIPSPACE:
|
||||
case ST_SKIPSPHEX:
|
||||
continue;
|
||||
case ST_HEXCOLON:
|
||||
if(xer_is_whitespace(lp, lstop - lp)) {
|
||||
lp = lstop - 1;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x2d: /* '-' */
|
||||
if(state == ST_SKIPSPACE) {
|
||||
|
@ -340,7 +374,24 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun
|
|||
break;
|
||||
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
|
||||
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
|
||||
if(state != ST_DIGITS) state = ST_DIGITS;
|
||||
switch(state) {
|
||||
case ST_DIGITS: break;
|
||||
case ST_SKIPSPHEX: /* Fall through */
|
||||
case ST_HEXDIGIT1:
|
||||
value = (lv - 0x30) << 4;
|
||||
state = ST_HEXDIGIT2;
|
||||
continue;
|
||||
case ST_HEXDIGIT2:
|
||||
value += (lv - 0x30);
|
||||
state = ST_HEXCOLON;
|
||||
st->buf[st->size++] = value;
|
||||
continue;
|
||||
case ST_HEXCOLON:
|
||||
return XPBD_BROKEN_ENCODING;
|
||||
default:
|
||||
state = ST_DIGITS;
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
long new_value = value * 10;
|
||||
|
@ -381,22 +432,86 @@ INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chun
|
|||
ASN_DEBUG("Unknown identifier for INTEGER");
|
||||
}
|
||||
return XPBD_BROKEN_ENCODING;
|
||||
case 0x3a: /* ':' */
|
||||
if(state == ST_HEXCOLON) {
|
||||
/* This colon is expected */
|
||||
state = ST_HEXDIGIT1;
|
||||
continue;
|
||||
} else if(state == ST_DIGITS) {
|
||||
/* The colon here means that we have
|
||||
* decoded the first two hexadecimal
|
||||
* places as a decimal value.
|
||||
* Switch decoding mode. */
|
||||
ASN_DEBUG("INTEGER re-evaluate as hex form");
|
||||
if(INTEGER_st_prealloc(st, (chunk_size/3) + 1))
|
||||
return XPBD_SYSTEM_FAILURE;
|
||||
state = ST_SKIPSPHEX;
|
||||
lp = lstart - 1;
|
||||
continue;
|
||||
} else {
|
||||
ASN_DEBUG("state %d at %d", state, lp - lstart);
|
||||
break;
|
||||
}
|
||||
/* [A-Fa-f] */
|
||||
case 0x41:case 0x42:case 0x43:case 0x44:case 0x45:case 0x46:
|
||||
case 0x61:case 0x62:case 0x63:case 0x64:case 0x65:case 0x66:
|
||||
switch(state) {
|
||||
case ST_SKIPSPHEX:
|
||||
case ST_SKIPSPACE: /* Fall through */
|
||||
case ST_HEXDIGIT1:
|
||||
value = lv - ((lv < 0x61) ? 0x41 : 0x61);
|
||||
value += 10;
|
||||
value <<= 4;
|
||||
state = ST_HEXDIGIT2;
|
||||
continue;
|
||||
case ST_HEXDIGIT2:
|
||||
value += lv - ((lv < 0x61) ? 0x41 : 0x61);
|
||||
value += 10;
|
||||
st->buf[st->size++] = value;
|
||||
state = ST_HEXCOLON;
|
||||
continue;
|
||||
case ST_DIGITS:
|
||||
ASN_DEBUG("INTEGER re-evaluate as hex form");
|
||||
if(INTEGER_st_prealloc(st, (chunk_size/3) + 1))
|
||||
return XPBD_SYSTEM_FAILURE;
|
||||
state = ST_SKIPSPHEX;
|
||||
lp = lstart - 1;
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Found extra non-numeric stuff */
|
||||
ASN_DEBUG("Found non-numeric 0x%2x at %d",
|
||||
lv, lp - lstart);
|
||||
state = ST_EXTRASTUFF;
|
||||
break;
|
||||
}
|
||||
|
||||
if(state != ST_DIGITS) {
|
||||
switch(state) {
|
||||
case ST_DIGITS:
|
||||
/* Everything is cool */
|
||||
break;
|
||||
case ST_HEXCOLON:
|
||||
st->buf[st->size] = 0; /* Just in case termination */
|
||||
return XPBD_BODY_CONSUMED;
|
||||
case ST_HEXDIGIT1:
|
||||
case ST_HEXDIGIT2:
|
||||
case ST_SKIPSPHEX:
|
||||
return XPBD_BROKEN_ENCODING;
|
||||
default:
|
||||
if(xer_is_whitespace(lp, lstop - lp)) {
|
||||
if(state != ST_EXTRASTUFF)
|
||||
return XPBD_NOT_BODY_IGNORE;
|
||||
/* Fall through */
|
||||
break;
|
||||
} else {
|
||||
ASN_DEBUG("No useful digits in output");
|
||||
ASN_DEBUG("INTEGER: No useful digits (state %d)",
|
||||
state);
|
||||
return XPBD_BROKEN_ENCODING; /* No digits */
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
value *= sign; /* Change sign, if needed */
|
||||
|
|
|
@ -35,8 +35,10 @@ extern asn_TYPE_descriptor_t *asn_pdu_collection[];
|
|||
* Open file and parse its contens.
|
||||
*/
|
||||
static void *data_decode_from_file(asn_TYPE_descriptor_t *asnTypeOfPDU,
|
||||
const char *fname, ssize_t suggested_bufsize);
|
||||
FILE *f, const char *filename, ssize_t suggested_bufsize);
|
||||
static int write_out(const void *buffer, size_t size, void *key);
|
||||
static FILE *argument_to_file(char *av[], int idx);
|
||||
static char *argument_to_name(char *av[], int idx);
|
||||
|
||||
int opt_debug; /* -d */
|
||||
static int opt_check; /* -c */
|
||||
|
@ -71,7 +73,7 @@ DEBUG(const char *fmt, ...) {
|
|||
}
|
||||
|
||||
int
|
||||
main(int ac, char **av) {
|
||||
main(int ac, char *av[]) {
|
||||
static asn_TYPE_descriptor_t *pduType = &PDU_Type;
|
||||
ssize_t suggested_bufsize = 8192; /* close or equal to stdio buffer */
|
||||
int number_of_iterations = 1;
|
||||
|
@ -206,15 +208,17 @@ main(int ac, char **av) {
|
|||
* Process all files in turn.
|
||||
*/
|
||||
for(ac_i = 0; ac_i < ac; ac_i++) {
|
||||
char *fname = av[ac_i];
|
||||
void *structure;
|
||||
asn_enc_rval_t erv;
|
||||
void *structure; /* Decoded structure */
|
||||
FILE *file = argument_to_file(av, ac_i);
|
||||
char *name = argument_to_name(av, ac_i);
|
||||
|
||||
/*
|
||||
* Decode the encoded structure from file.
|
||||
*/
|
||||
structure = data_decode_from_file(pduType,
|
||||
fname, suggested_bufsize);
|
||||
file, name, suggested_bufsize);
|
||||
if(file && file != stdin) fclose(file);
|
||||
if(!structure) {
|
||||
/* Error message is already printed */
|
||||
exit(EX_DATAERR);
|
||||
|
@ -227,14 +231,14 @@ main(int ac, char **av) {
|
|||
if(asn_check_constraints(pduType, structure,
|
||||
errbuf, &errlen)) {
|
||||
fprintf(stderr, "%s: ASN.1 constraint "
|
||||
"check failed: %s\n", fname, errbuf);
|
||||
"check failed: %s\n", name, errbuf);
|
||||
exit(EX_DATAERR);
|
||||
}
|
||||
}
|
||||
|
||||
switch(oform) {
|
||||
case OUT_NULL:
|
||||
fprintf(stderr, "%s: decoded successfully\n", fname);
|
||||
fprintf(stderr, "%s: decoded successfully\n", name);
|
||||
break;
|
||||
case OUT_TEXT: /* -otext */
|
||||
asn_fprint(stdout, pduType, structure);
|
||||
|
@ -242,7 +246,7 @@ main(int ac, char **av) {
|
|||
case OUT_XER: /* -oxer */
|
||||
if(xer_fprint(stdout, pduType, structure)) {
|
||||
fprintf(stderr, "%s: Cannot convert into XML\n",
|
||||
fname);
|
||||
name);
|
||||
exit(EX_UNAVAILABLE);
|
||||
}
|
||||
break;
|
||||
|
@ -250,7 +254,7 @@ main(int ac, char **av) {
|
|||
erv = der_encode(pduType, structure, write_out, stdout);
|
||||
if(erv.encoded < 0) {
|
||||
fprintf(stderr, "%s: Cannot convert into DER\n",
|
||||
fname);
|
||||
name);
|
||||
exit(EX_UNAVAILABLE);
|
||||
}
|
||||
break;
|
||||
|
@ -258,7 +262,7 @@ main(int ac, char **av) {
|
|||
erv = uper_encode(pduType, structure, write_out, stdout);
|
||||
if(erv.encoded < 0) {
|
||||
fprintf(stderr, "%s: Cannot convert into Unaligned PER\n",
|
||||
fname);
|
||||
name);
|
||||
exit(EX_UNAVAILABLE);
|
||||
}
|
||||
break;
|
||||
|
@ -325,7 +329,8 @@ static void add_bytes_to_buffer(const void *data2add, size_t bySize) {
|
|||
DynamicBuffer.length += bySize;
|
||||
}
|
||||
|
||||
static void *data_decode_from_file(asn_TYPE_descriptor_t *pduType, const char *fname, ssize_t suggested_bufsize) {
|
||||
static void *
|
||||
data_decode_from_file(asn_TYPE_descriptor_t *pduType, FILE *file, const char *filename, ssize_t suggested_bufsize) {
|
||||
static char *fbuf;
|
||||
static ssize_t fbuf_size;
|
||||
static asn_codec_ctx_t s_codec_ctx;
|
||||
|
@ -333,26 +338,18 @@ static void *data_decode_from_file(asn_TYPE_descriptor_t *pduType, const char *f
|
|||
void *structure = 0;
|
||||
asn_dec_rval_t rval;
|
||||
size_t rd;
|
||||
FILE *fp;
|
||||
|
||||
if(!file) {
|
||||
fprintf(stderr, "%s: %s\n", filename, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(opt_stack) {
|
||||
s_codec_ctx.max_stack_size = opt_stack;
|
||||
opt_codec_ctx = &s_codec_ctx;
|
||||
}
|
||||
|
||||
if(strcmp(fname, "-")) {
|
||||
DEBUG("Processing file %s", fname);
|
||||
fp = fopen(fname, "r");
|
||||
} else {
|
||||
DEBUG("Processing %s", "standard input");
|
||||
fname = "stdin";
|
||||
fp = stdin;
|
||||
}
|
||||
|
||||
if(!fp) {
|
||||
fprintf(stderr, "%s: %s\n", fname, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
DEBUG("Processing %s", filename);
|
||||
|
||||
/* prepare the file buffer */
|
||||
if(fbuf_size != suggested_bufsize) {
|
||||
|
@ -374,7 +371,7 @@ static void *data_decode_from_file(asn_TYPE_descriptor_t *pduType, const char *f
|
|||
rval.code = RC_WMORE;
|
||||
rval.consumed = 0;
|
||||
|
||||
while((rd = fread(fbuf, 1, fbuf_size, fp)) || !feof(fp)) {
|
||||
while((rd = fread(fbuf, 1, fbuf_size, file)) || !feof(file)) {
|
||||
char *i_bptr;
|
||||
size_t i_size;
|
||||
|
||||
|
@ -425,7 +422,6 @@ static void *data_decode_from_file(asn_TYPE_descriptor_t *pduType, const char *f
|
|||
case RC_OK:
|
||||
DEBUG("RC_OK, finishing up with %ld",
|
||||
(long)rval.consumed);
|
||||
if(fp != stdin) fclose(fp);
|
||||
return structure;
|
||||
case RC_WMORE:
|
||||
/*
|
||||
|
@ -448,14 +444,12 @@ static void *data_decode_from_file(asn_TYPE_descriptor_t *pduType, const char *f
|
|||
break;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
/* Clean up partially decoded structure */
|
||||
ASN_STRUCT_FREE(*pduType, structure);
|
||||
|
||||
fprintf(stderr, "%s: "
|
||||
"Decode failed past byte %ld: %s\n",
|
||||
fname, (long)(DynamicBuffer.bytes_shifted
|
||||
filename, (long)(DynamicBuffer.bytes_shifted
|
||||
+ DynamicBuffer.offset + rval.consumed),
|
||||
(rval.code == RC_WMORE)
|
||||
? "Unexpected end of input"
|
||||
|
@ -469,3 +463,27 @@ static int write_out(const void *buffer, size_t size, void *key) {
|
|||
FILE *fp = (FILE *)key;
|
||||
return (fwrite(buffer, 1, size, fp) == size) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int argument_is_stdin(char *av[], int idx) {
|
||||
if(strcmp(av[idx], "-")) {
|
||||
return 0; /* Certainly not <stdin> */
|
||||
} else {
|
||||
/* This might be <stdin>, unless `./program -- -` */
|
||||
if(strcmp(av[-1], "--"))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static FILE *argument_to_file(char *av[], int idx) {
|
||||
return argument_is_stdin(av, idx)
|
||||
? stdin
|
||||
: fopen(av[idx], "r");
|
||||
}
|
||||
|
||||
static char *argument_to_name(char *av[], int idx) {
|
||||
return argument_is_stdin(av, idx)
|
||||
? "standard input"
|
||||
: av[idx];
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue