static void check_xer(int tofail, char *xmldata, long orig_value) { INTEGER_t *st = 0; asn_dec_rval_t rc; long value; int ret; printf("[%s] vs %ld: ", xmldata, orig_value); rc = xer_decode(0, &asn_DEF_INTEGER, (void *)&st, xmldata, strlen(xmldata)); if(rc.code != RC_OK) { assert(tofail); printf("\tfailed, as expected\n"); return; } assert(!tofail); ret = asn_INTEGER2long(st, &value); assert(ret == 0); printf("\t%ld\n", value); assert(value == orig_value); asn_DEF_INTEGER.free_struct(&asn_DEF_INTEGER, st, 0); }
void * asn1_decode_object(asn_TYPE_descriptor_t *td, VALUE encoder_v, VALUE byte_string) { asn_dec_rval_t rval; asn_codec_ctx_t context; context.max_stack_size = 0; void *st = NULL; char *str, *encoder; int length; encoder = encoder_string(encoder_v); /* * 1. Retrive BER string and its length. */ str = RSTRING_PTR(byte_string); length = RSTRING_LEN(byte_string); if (strcmp(encoder, "der") == 0 || strcmp(encoder, "ber") == 0) { rval = td->ber_decoder(&context, td, (void **)&st, (void *)str, length, 0); if (rval.code != RC_OK) { rb_raise(rb_eException, "Can't decode type"); } } else if (strcmp(encoder, "per") == 0) { asn_per_data_t apd; apd.buffer = str; apd.nboff = 0; apd.nbits = length * 8; apd.moved = 0; apd.refill = NULL; apd.refill_key = NULL; rval = td->uper_decoder(&context, td, td->per_constraints, (void **)&st, &apd); if (rval.code != RC_OK) { rb_raise(rb_eException, "Can't decode type"); } } else if (strcmp(encoder, "xer") == 0) { rval = xer_decode(0, td, (void **)&st, str, length); if (rval.code != RC_OK) { rb_raise(rb_eException, "Can't decode type"); } } return st; }
static void check_xer(e_Enum2 eval, char *xer_string) { asn_dec_rval_t rv; char buf2[128]; Enum2_t *e = 0; long val; rv = xer_decode(0, &asn_DEF_Enum2, (void **)&e, xer_string, strlen(xer_string)); assert(rv.code == RC_OK); assert(rv.consumed == strlen(xer_string)); asn_INTEGER2long(e, &val); printf("%s -> %ld == %d\n", xer_string, val, eval); assert(val == eval); buf_offset = 0; xer_encode(&asn_DEF_Enum2, e, XER_F_CANONICAL, buf_writer, 0); buf[buf_offset] = 0; sprintf(buf2, "<Enum2>%s</Enum2>", xer_string); printf("%d -> %s == %s\n", eval, buf, buf2); assert(0 == strcmp(buf, buf2)); }
static PDU_t * load_object_from(const char *fname, char *fbuf, int size, enum enctype how, int mustfail) { asn_dec_rval_t rval; PDU_t *st = 0; int csize = 1; if(getenv("INITIAL_CHUNK_SIZE")) csize = atoi(getenv("INITIAL_CHUNK_SIZE")); /* Perform multiple iterations with multiple chunks sizes */ for(; csize < 20; csize += 1) { int fbuf_offset = 0; int fbuf_left = size; int fbuf_chunk = csize; fprintf(stderr, "LOADING OBJECT OF SIZE %d FROM [%s] as %s," " chunks %d\n", size, fname, how==AS_PER?"PER":"XER", csize); if(st) asn_DEF_PDU.free_struct(&asn_DEF_PDU, st, 0); st = 0; do { fprintf(stderr, "\nDecoding bytes %d..%d (left %d) [%s]\n", fbuf_offset, fbuf_chunk < fbuf_left ? fbuf_chunk : fbuf_left, fbuf_left, fname); if(st) { fprintf(stderr, "=== currently ===\n"); asn_fprint(stderr, &asn_DEF_PDU, st); fprintf(stderr, "=== end ===\n"); } switch(how) { case AS_XER: rval = xer_decode(0, &asn_DEF_PDU, (void **)&st, fbuf + fbuf_offset, fbuf_chunk < fbuf_left ? fbuf_chunk : fbuf_left); break; case AS_DER: assert(0); break; case AS_PER: rval = uper_decode(0, &asn_DEF_PDU, (void **)&st, fbuf + fbuf_offset, fbuf_chunk < fbuf_left ? fbuf_chunk : fbuf_left, 0, 0); if(rval.code == RC_WMORE) { if(fbuf_chunk == fbuf_left) { fprintf(stderr, "-> PER decode error (%d bits of %d bytes (c=%d,l=%d)) \n", rval.consumed, size, fbuf_chunk, fbuf_left); rval.code = RC_FAIL; rval.consumed += 7; rval.consumed /= 8; if(mustfail) { fprintf(stderr, "-> (this was expected failure)\n"); return 0; } } else { rval.consumed = 0; /* Not restartable */ ASN_STRUCT_FREE(asn_DEF_PDU, st); st = 0; fprintf(stderr, "-> PER wants more\n"); } } else { fprintf(stderr, "-> PER ret %d/%d mf=%d\n", rval.code, rval.consumed, mustfail); /* uper_decode() returns _bits_ */ rval.consumed += 7; rval.consumed /= 8; if((mustfail?1:0) == (rval.code == RC_FAIL)) { if(mustfail) { fprintf(stderr, "-> (this was expected failure)\n"); return 0; } } else { fprintf(stderr, "-> (unexpected %s)\n", mustfail ? "success" : "failure"); rval.code = RC_FAIL; } } break; } fbuf_offset += rval.consumed; fbuf_left -= rval.consumed; if(rval.code == RC_WMORE) fbuf_chunk += 1; /* Give little more */ else fbuf_chunk = csize; /* Back off */ } while(fbuf_left && rval.code == RC_WMORE); assert(rval.code == RC_OK); if(how == AS_PER) { fprintf(stderr, "[left %d, off %d, size %d]\n", fbuf_left, fbuf_offset, size); assert(fbuf_offset == size); } else { assert(fbuf_offset - size < 2 || (fbuf_offset + 1 /* "\n" */ == size && fbuf[size - 1] == '\n') || (fbuf_offset + 2 /* "\r\n" */ == size && fbuf[size - 2] == '\r' && fbuf[size - 1] == '\n') ); } } if(st) asn_fprint(stderr, &asn_DEF_PDU, st); return st; }
static PDU_t * load_object_from(const char *fname, enum expectation expectation, char *fbuf, size_t size, enum enctype how) { asn_dec_rval_t rval; PDU_t *st = 0; size_t csize = 1; if(getenv("INITIAL_CHUNK_SIZE")) csize = atoi(getenv("INITIAL_CHUNK_SIZE")); /* Perform multiple iterations with multiple chunks sizes */ for(; csize < 20; csize += 1) { int fbuf_offset = 0; int fbuf_left = size; int fbuf_chunk = csize; fprintf(stderr, "LOADING OBJECT OF SIZE %zd FROM [%s] as %s," " chunks %zd\n", size, fname, how==AS_PER?"PER":"XER", csize); if(st) asn_DEF_PDU.free_struct(&asn_DEF_PDU, st, 0); st = 0; do { fprintf(stderr, "Decoding bytes %d..%d (left %d)\n", fbuf_offset, fbuf_chunk < fbuf_left ? fbuf_chunk : fbuf_left, fbuf_left); if(st) { fprintf(stderr, "=== currently ===\n"); asn_fprint(stderr, &asn_DEF_PDU, st); fprintf(stderr, "=== end ===\n"); } switch(how) { case AS_XER: rval = xer_decode(0, &asn_DEF_PDU, (void **)&st, fbuf + fbuf_offset, fbuf_chunk < fbuf_left ? fbuf_chunk : fbuf_left); break; case AS_PER: rval = uper_decode(0, &asn_DEF_PDU, (void **)&st, fbuf + fbuf_offset, fbuf_chunk < fbuf_left ? fbuf_chunk : fbuf_left, 0, 0); if(rval.code == RC_WMORE) { rval.consumed = 0; /* Not restartable */ ASN_STRUCT_FREE(asn_DEF_PDU, st); st = 0; fprintf(stderr, "-> PER wants more\n"); } else { fprintf(stderr, "-> PER ret %d/%ld\n", rval.code, rval.consumed); /* uper_decode() returns _bits_ */ rval.consumed += 7; rval.consumed /= 8; } break; } fbuf_offset += rval.consumed; fbuf_left -= rval.consumed; if(rval.code == RC_WMORE) fbuf_chunk += 1; /* Give little more */ else fbuf_chunk = csize; /* Back off */ } while(fbuf_left && rval.code == RC_WMORE); if(expectation != EXP_BROKEN) { assert(rval.code == RC_OK); if(how == AS_PER) { fprintf(stderr, "[left %d, off %d, size %zd]\n", fbuf_left, fbuf_offset, size); assert(fbuf_offset == size); } else { assert(fbuf_offset - size < 2 || (fbuf_offset + 1 /* "\n" */ == size && fbuf[size - 1] == '\n') || (fbuf_offset + 2 /* "\r\n" */ == size && fbuf[size - 2] == '\r' && fbuf[size - 1] == '\n') ); } } else { assert(rval.code != RC_OK); fprintf(stderr, "Failed, but this was expected\n"); asn_DEF_PDU.free_struct(&asn_DEF_PDU, st, 0); st = 0; /* ignore leak for now */ } } if(st) asn_fprint(stderr, &asn_DEF_PDU, st); return st; }
enum xer_equivalence_e xer_equivalent(const struct asn_TYPE_descriptor_s *td, const void *struct1, const void *struct2, FILE *opt_debug_stream) { struct xer_buffer xb1 = {0, 0, 0}; struct xer_buffer xb2 = {0, 0, 0}; asn_enc_rval_t e1, e2; asn_dec_rval_t rval; void *sptr = NULL; if(!td || !struct1 || !struct2) { if(opt_debug_stream) { if(!td) fprintf(opt_debug_stream, "Type descriptor missing\n"); if(!struct1) fprintf(opt_debug_stream, "Structure 1 missing\n"); if(!struct2) fprintf(opt_debug_stream, "Structure 2 missing\n"); } return XEQ_FAILURE; } e1 = xer_encode(td, struct1, XER_F_BASIC, xer__buffer_append, &xb1); if(e1.encoded == -1) { if(opt_debug_stream) { fprintf(stderr, "XER Encoding of %s failed\n", td->name); } FREEMEM(xb1.buffer); return XEQ_ENCODE1_FAILED; } e2 = xer_encode(td, struct2, XER_F_BASIC, xer__buffer_append, &xb2); if(e2.encoded == -1) { if(opt_debug_stream) { fprintf(stderr, "XER Encoding of %s failed\n", td->name); } FREEMEM(xb1.buffer); FREEMEM(xb2.buffer); return XEQ_ENCODE1_FAILED; } if(xb1.buffer_size != xb2.buffer_size || memcmp(xb1.buffer, xb2.buffer, xb1.buffer_size) != 0) { if(opt_debug_stream) { fprintf(opt_debug_stream, "Structures XER-encoded into different byte streams:\n=== " "Structure 1 ===\n%s\n=== Structure 2 ===\n%s\n", xb1.buffer, xb2.buffer); } FREEMEM(xb1.buffer); FREEMEM(xb2.buffer); return XEQ_DIFFERENT; } else { if(opt_debug_stream) { fprintf(opt_debug_stream, "Both structures encoded into the same XER byte stream " "of size %" ASN_PRI_SIZE ":\n%s", xb1.buffer_size, xb1.buffer); } } rval = xer_decode(NULL, td, (void **)&sptr, xb1.buffer, xb1.buffer_size); switch(rval.code) { case RC_OK: break; case RC_WMORE: if(opt_debug_stream) { fprintf(opt_debug_stream, "Structure %s XER decode unexpectedly requires " "more data:\n%s\n", td->name, xb1.buffer); } /* Fall through */ case RC_FAIL: default: if(opt_debug_stream) { fprintf(opt_debug_stream, "Structure %s XER decoding resulted in failure.\n", td->name); } ASN_STRUCT_FREE(*td, sptr); FREEMEM(xb1.buffer); FREEMEM(xb2.buffer); return XEQ_DECODE_FAILED; } if(rval.consumed != xb1.buffer_size && ((rval.consumed > xb1.buffer_size) || xer_whitespace_span(xb1.buffer + rval.consumed, xb1.buffer_size - rval.consumed) != (xb1.buffer_size - rval.consumed))) { if(opt_debug_stream) { fprintf(opt_debug_stream, "Round-trip decode of %s required less bytes (%" ASN_PRI_SIZE ") than " "encoded (%" ASN_PRI_SIZE ")\n", td->name, rval.consumed, xb1.buffer_size); } ASN_STRUCT_FREE(*td, sptr); FREEMEM(xb1.buffer); FREEMEM(xb2.buffer); return XEQ_ROUND_TRIP_FAILED; } /* * Reuse xb2 to encode newly decoded structure. */ FREEMEM(xb2.buffer); memset(&xb2, 0, sizeof(xb2)); e2 = xer_encode(td, sptr, XER_F_BASIC, xer__buffer_append, &xb2); if(e2.encoded == -1) { if(opt_debug_stream) { fprintf(stderr, "XER Encoding of round-trip decode of %s failed\n", td->name); } ASN_STRUCT_FREE(*td, sptr); FREEMEM(xb1.buffer); FREEMEM(xb2.buffer); return XEQ_ROUND_TRIP_FAILED; } ASN_STRUCT_FREE(*td, sptr); sptr = 0; if(xb1.buffer_size != xb2.buffer_size || memcmp(xb1.buffer, xb2.buffer, xb1.buffer_size) != 0) { if(opt_debug_stream) { fprintf(opt_debug_stream, "XER Encoding of round-trip decode of %s resulted in " "different byte stream:\n" "=== Original ===\n%s\n" "=== Round-tripped ===\n%s\n", xb1.buffer, xb2.buffer, td->name); } FREEMEM(xb1.buffer); FREEMEM(xb2.buffer); return XEQ_ROUND_TRIP_FAILED; } FREEMEM(xb1.buffer); FREEMEM(xb2.buffer); return XEQ_SUCCESS; }