XER can decode long values

This commit is contained in:
Lev Walkin 2006-09-15 18:33:25 +00:00
parent 55f106a8b2
commit c744a02926
7 changed files with 222 additions and 37 deletions

View File

@ -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

View File

@ -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)'

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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 */

View File

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