Beispiel #1
0
int main() {
    LDAPMessage_t *req_bind, *req_search, *req_unbind;
    LDAPMessage_t *rsp_bind, *rsp_search1, *rsp_search2, *rsp_search_done;

    int sock = accept_single_connection(3389);

    fprintf(stderr, "Receiving LDAP message...\n");
    req_bind = receive_ldap_message(sock);
    assert(req_bind);
    assert(req_bind->protocolOp.present == LDAPMessage__protocolOp_PR_bindRequest);
    assert(req_bind->protocolOp.choice.bindRequest.version == 3);
    fprintf(stderr, "Received BindRequest...\n");
    asn_fprint(stderr, &asn_DEF_LDAPMessage, req_bind);

    fprintf(stderr, "Sending BindReply...\n");
    rsp_bind = bind_response_ok(req_bind->messageID, &req_bind->protocolOp.choice.bindRequest.name);
    asn_fprint(stderr, &asn_DEF_LDAPMessage, rsp_bind);
    send_ldap_message(sock, rsp_bind);

    req_search = receive_ldap_message(sock);
    assert(req_search->protocolOp.present == LDAPMessage__protocolOp_PR_searchRequest);
    fprintf(stderr, "Received SearchRequest...\n");
    xer_fprint(stderr, &asn_DEF_LDAPMessage, req_search);

    rsp_search1 = search_result_entry(req_search->messageID, "Lev Walkin", "*****@*****.**", "avatar.jpg");
    asn_fprint(stderr, &asn_DEF_LDAPMessage, rsp_search1);
    send_ldap_message(sock, rsp_search1);

    rsp_search2 = search_result_entry(req_search->messageID, "Olga Bobrova", "*****@*****.**", NULL);
    asn_fprint(stderr, &asn_DEF_LDAPMessage, rsp_search2);
    send_ldap_message(sock, rsp_search2);

    rsp_search_done = search_result_done(req_search->messageID, &req_search->protocolOp.choice.searchRequest.baseObject);
    asn_fprint(stderr, &asn_DEF_LDAPMessage, rsp_search_done);
    send_ldap_message(sock, rsp_search_done);

    req_unbind = receive_ldap_message(sock);
    assert(req_unbind->protocolOp.present == LDAPMessage__protocolOp_PR_unbindRequest);
    xer_fprint(stderr, &asn_DEF_LDAPMessage, req_unbind);

    ASN_STRUCT_FREE(asn_DEF_LDAPMessage, req_bind);
    ASN_STRUCT_FREE(asn_DEF_LDAPMessage, req_search);
    ASN_STRUCT_FREE(asn_DEF_LDAPMessage, req_unbind);
    ASN_STRUCT_FREE(asn_DEF_LDAPMessage, rsp_bind);
    ASN_STRUCT_FREE(asn_DEF_LDAPMessage, rsp_search1);
    ASN_STRUCT_FREE(asn_DEF_LDAPMessage, rsp_search2);
    ASN_STRUCT_FREE(asn_DEF_LDAPMessage, rsp_search_done);

    return 0;
}
Beispiel #2
0
static int
save_object(void *bs, asn_TYPE_descriptor_t *td) {
	asn_enc_rval_t rval; /* Return value */
	int i;
	
	rval = der_encode(td, bs, _buf_writer, 0);
	if (rval.encoded == -1) {
		fprintf(stderr,
			"Cannot encode %s: %s\n",
			rval.failed_type->name, strerror(errno));
		assert(rval.encoded != -1);
		return -1;	/* JIC */
	}

	buf[buf_offset++] = 123;	/* Finalize with garbage */

	asn_fprint(stderr, td, bs);
	xer_fprint(stderr, td, bs);

	printf("OUT: [");
	for(i = 0; i < buf_offset; i++)
		printf(" %02x", buf[i]);
	printf("]\n");

	return 0;
}
Beispiel #3
0
static void ent_debug(const char *str, LDAPMessage_t *msg)
{
    if (!config.debug) {
        return;
    }
    fprintf(stdout, "%s\n", str);
    asn_fprint(stdout, &asn_DEF_LDAPMessage, msg);
    fprintf(stdout, "\n");
}
static int
load_object(void *bs, asn_TYPE_descriptor_t *td) {
	asn_dec_rval_t rval;

	fprintf(stderr, "\nLOADING OBJECT OF SIZE %d\n", buf_offset);

	rval = ber_decode(0, td, (void **)&bs, buf, buf_offset);
	assert(rval.code == RC_OK);

	asn_fprint(stderr, td, bs);

	return (rval.code == RC_OK)?0:-1;
}
int
main(int ac, char **av) {
	T_t t;

	(void)ac;	/* Unused argument */
	(void)av;	/* Unused argument */

	/* Check exact buf1 */
	check(&t, buf1, sizeof(buf1), sizeof(buf1));
	compare(&t, buf1_reconstr, sizeof(buf1_reconstr));
	asn_fprint(stderr, &asn_DEF_T, &t);
	asn_DEF_T.free_struct(&asn_DEF_T, &t, 1);

	/* Check slightly more than buf1 */
	check(&t, buf1, sizeof(buf1) + 10, sizeof(buf1));
	compare(&t, buf1_reconstr, sizeof(buf1_reconstr));
	asn_fprint(stderr, &asn_DEF_T, &t);
	asn_DEF_T.free_struct(&asn_DEF_T, &t, 1);

	/* Split the buffer in parts and check decoder restartability */
	partial_read(buf1, sizeof(buf1));

	return 0;
}
static void
check(LogLine_t *tp, uint8_t *ptr, int size, size_t consumed) {
	asn_dec_rval_t rval;

	tp = memset(tp, 0, sizeof(*tp));

	fprintf(stderr, "Buf %p (%d)\n", ptr, size);
	rval = ber_decode(0, &asn_DEF_LogLine, (void **)&tp, ptr, size);
	fprintf(stderr, "Returned code %d, consumed %d\n",
		(int)rval.code, (int)rval.consumed);

	assert(rval.code == RC_OK);
	assert(rval.consumed == consumed);
	asn_fprint(stderr, &asn_DEF_LogLine, tp);
	asn_DEF_LogLine.free_struct(&asn_DEF_LogLine, tp, 1);
}
static void
check_serialize() {
	LogLine_t ll;
	VariablePartSet_t vps;
	VariablePart_t vp;
	VisibleString_t vpart;
	asn_enc_rval_t erval;
	int i;

	memset(&ll, 0, sizeof(ll));
	memset(&vps, 0, sizeof(vps));
	memset(&vp, 0, sizeof(vp));
	memset(&vpart, 0, sizeof(vpart));
	vpart.buf = "123";
	vpart.size = 3;

	vp.present = VariablePart_PR_vset;
	ASN_SET_ADD(&vp.choice.vset, &vpart);
	vps.resolution.accept_as = accept_as_unknown;
	ASN_SEQUENCE_ADD(&vps.vparts, &vp);
	ASN_SEQUENCE_ADD(&ll.varsets, &vps);
	ll.line_digest.buf = "zzz\007";
	ll.line_digest.size = 4;

	asn_fprint(stderr, &asn_DEF_LogLine, &ll);
	buf_size = 128;
	buf = alloca(buf_size);
	erval = der_encode(&asn_DEF_LogLine, &ll, buf_fill, 0);
	assert(erval.encoded > 1);
	fprintf(stderr, "Encoded in %d bytes\n", erval.encoded);
	fprintf(stderr, "\n");
	for(i = 0; i < buf_pos; i++) {
		fprintf(stderr, "%d ", buf[i]);
	}
	fprintf(stderr, "\n\n");
	assert(erval.encoded == sizeof(buf0));
	assert(memcmp(buf0, buf, sizeof(buf0)) == 0);
}
Beispiel #8
0
void test_AddRequest()
{
	/// Building a AddRequest ///

	DNDSMessage_t *msg;		// a DNDS Message
	DNDSObject_t *objClient;	// a DS Object

	DNDSMessage_new(&msg);
//	DNDSMessage_set_version(msg, 1);
	DNDSMessage_set_channel(msg, 0);
	DNDSMessage_set_pdu(msg, pdu_PR_dsm);	// Directory Service Message

	DSMessage_set_seqNumber(msg, 1);
	DSMessage_set_ackNumber(msg, 1);	// seq XOR ack
	DSMessage_set_operation(msg, dsop_PR_addRequest);
//	DSMessage_set_action(msg, action_addClient);

	AddRequest_set_objectType(msg, DNDSObject_PR_client, &objClient);

//	Client_set_id(objClient, 987);
	Client_set_email(objClient, "test@test", 9);
	Client_set_password(objClient, "test", 4);
//	Client_set_status(objClient, 0);

	/// Encoding part

	asn_enc_rval_t ec;	// Encoder return value
	FILE *fp = fopen("dnds.ber", "wb"); // BER output
	ec = der_encode(&asn_DEF_DNDSMessage, msg, write_out, fp);
	fclose(fp);

	xer_fprint(stdout, &asn_DEF_DNDSMessage, msg);

	asn_fprint(stdout, &asn_DEF_DNDSMessage, msg);


	DNDSMessage_del(msg);
}
Beispiel #9
0
static void
check_serialize() {
	LogLine_t ll;
	VariablePartSet_t *vps;
	VariablePart_t *vp;
	VisibleString_t *vpart;
	asn_enc_rval_t erval;
	int i;

	memset(&ll, 0, sizeof(ll));
	vps = calloc(1, sizeof(*vps));
	vp = calloc(1, sizeof(*vp));
	vpart = OCTET_STRING_new_fromBuf(&asn_DEF_VisibleString, "123", 3);

	vp->present = VariablePart_PR_vset;
	ASN_SET_ADD(&vp->choice.vset, vpart);
	vps->resolution.accept_as = accept_as_unknown;
	ASN_SEQUENCE_ADD(&vps->vparts, vp);
	ASN_SEQUENCE_ADD(&ll.varsets, vps);
	OCTET_STRING_fromBuf(&ll.line_digest, "zzz\007", 4);

	asn_fprint(stderr, &asn_DEF_LogLine, &ll);
	buf_size = 128;
	uint8_t scratch[buf_size];
	buf = scratch;
	erval = der_encode(&asn_DEF_LogLine, &ll, buf_fill, 0);
	assert(erval.encoded > 1);
	fprintf(stderr, "Encoded in %zd bytes\n", erval.encoded);
	fprintf(stderr, "\n");
	for(i = 0; i < buf_pos; i++) {
		fprintf(stderr, "%d ", buf[i]);
	}
	fprintf(stderr, "\n\n");
	assert(erval.encoded == sizeof(buf0));
	assert(memcmp(buf0, buf, sizeof(buf0)) == 0);
	ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_LogLine, &ll);
	return;
}
Beispiel #10
0
int
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;
	int num;
	int ch;

	pduInit();

	/* Figure out if Unaligned PER needs to be default */
	if(pduType->uper_decoder)
		iform = INP_PER;

	/*
	 * Pocess the command-line argments.
	 */
	while((ch = getopt(ac, av, "i:o:1b:cdn:p:hs:" JUNKOPT)) != -1)
	switch(ch) {
	case 'i':
		if(optarg[0] == 'b') { iform = INP_BER; break; }
		if(optarg[0] == 'x') { iform = INP_XER; break; }
		if(pduType->uper_decoder
		&& optarg[0] == 'p') { iform = INP_PER; break; }
		fprintf(stderr, "-i<format>: '%s': improper format selector\n",
			optarg);
		exit(EX_UNAVAILABLE);
	case 'o':
		if(optarg[0] == 'd') { oform = OUT_DER; break; }
		if(pduType->uper_encoder
		&& optarg[0] == 'p') { oform = OUT_PER; break; }
		if(optarg[0] == 'x') { oform = OUT_XER; break; }
		if(optarg[0] == 't') { oform = OUT_TEXT; break; }
		if(optarg[0] == 'n') { oform = OUT_NULL; break; }
		fprintf(stderr, "-o<format>: '%s': improper format selector\n",
			optarg);
		exit(EX_UNAVAILABLE);
	case '1':
		opt_onepdu = 1;
		break;
	case 'b':
		suggested_bufsize = atoi(optarg);
		if(suggested_bufsize < 1
			|| suggested_bufsize > 16 * 1024 * 1024) {
			fprintf(stderr,
				"-b %s: Improper buffer size (1..16M)\n",
				optarg);
			exit(EX_UNAVAILABLE);
		}
		break;
	case 'c':
		opt_check = 1;
		break;
	case 'd':
		opt_debug++;	/* Double -dd means ASN.1 debug */
		break;
	case 'n':
		number_of_iterations = atoi(optarg);
		if(number_of_iterations < 1) {
			fprintf(stderr,
				"-n %s: Improper iterations count\n", optarg);
			exit(EX_UNAVAILABLE);
		}
		break;
	case 'p':
		if(strcmp(optarg, "er-nopad") == 0) {
			opt_nopad = 1;
			break;
		}
#ifdef	ASN_PDU_COLLECTION
		if(strcmp(optarg, "list") == 0) {
			asn_TYPE_descriptor_t **pdu = asn_pdu_collection;
			fprintf(stderr, "Available PDU types:\n");
			for(; *pdu; pdu++) printf("%s\n", (*pdu)->name);
			exit(0);
		} else if(optarg[0] >= 'A' && optarg[0] <= 'Z') {
			asn_TYPE_descriptor_t **pdu = asn_pdu_collection;
			while(*pdu && strcmp((*pdu)->name, optarg)) pdu++;
			if(*pdu) { pduType = *pdu; break; }
			fprintf(stderr, "-p %s: Unrecognized PDU\n", optarg);
		}
#endif	/* ASN_PDU_COLLECTION */
		fprintf(stderr, "-p %s: Unrecognized option\n", optarg);
		exit(EX_UNAVAILABLE);
	case 's':
		opt_stack = atoi(optarg);
		if(opt_stack < 0) {
			fprintf(stderr,
				"-s %s: Non-negative value expected\n",
				optarg);
			exit(EX_UNAVAILABLE);
		}
		break;
#ifdef	JUNKTEST
	case 'J':
		opt_jprob = strtod(optarg, 0);
		if(opt_jprob <= 0.0 || opt_jprob > 1.0) {
			fprintf(stderr,
				"-J %s: Probability range 0..1 expected \n",
				optarg);
			exit(EX_UNAVAILABLE);
		}
		break;
#endif	/* JUNKTEST */
	case 'h':
	default:
#ifdef	ASN_CONVERTER_TITLE
#define	_AXS(x)	#x
#define	_ASX(x)	_AXS(x)
		fprintf(stderr, "%s\n", _ASX(ASN_CONVERTER_TITLE));
#endif
		fprintf(stderr, "Usage: %s [options] <data.ber> ...\n", av[0]);
		fprintf(stderr, "Where options are:\n");
		if(pduType->uper_decoder)
		fprintf(stderr,
		"  -iper        Input is in Unaligned PER (Packed Encoding Rules) (DEFAULT)\n");
		fprintf(stderr,
		"  -iber        Input is in BER (Basic Encoding Rules)%s\n",
			iform == INP_PER ? "" : " (DEFAULT)");
		fprintf(stderr,
		"  -ixer        Input is in XER (XML Encoding Rules)\n");
		if(pduType->uper_encoder)
		fprintf(stderr,
		"  -oper        Output in Unaligned PER (Packed Encoding Rules)\n");
		fprintf(stderr,
		"  -oder        Output in DER (Distinguished Encoding Rules)\n"
		"  -oxer        Output in XER (XML Encoding Rules) (DEFAULT)\n"
		"  -otext       Output in plain semi-structured text (dump)\n"
		"  -onull       Verify (decode) input, but do not output\n");
		if(pduType->uper_decoder)
		fprintf(stderr,
		"  -per-nopad   Assume PER PDUs are not padded (-iper)\n");
#ifdef	ASN_PDU_COLLECTION
		fprintf(stderr,
		"  -p <PDU>     Specify PDU type to decode\n"
		"  -p list      List available PDUs\n");
#endif	/* ASN_PDU_COLLECTION */
		fprintf(stderr,
		"  -1           Decode only the first PDU in file\n"
		"  -b <size>    Set the i/o buffer size (default is %ld)\n"
		"  -c           Check ASN.1 constraints after decoding\n"
		"  -d           Enable debugging (-dd is even better)\n"
		"  -n <num>     Process files <num> times\n"
		"  -s <size>    Set the stack usage limit (default is %d)\n"
#ifdef	JUNKTEST
		"  -J <prob>    Set random junk test bit garbaging probability\n"
#endif
		, (long)suggested_bufsize, _ASN_DEFAULT_STACK_MAX);
		exit(EX_USAGE);
	}

	ac -= optind;
	av += optind;

	if(ac < 1) {
		fprintf(stderr, "%s: No input files specified. "
				"Try '-h' for more information\n",
				av[-optind]);
		exit(EX_USAGE);
	}

	setvbuf(stdout, 0, _IOLBF, 0);

	for(num = 0; num < number_of_iterations; num++) {
	  int ac_i;
	  /*
	   * Process all files in turn.
	   */
	  for(ac_i = 0; ac_i < ac; ac_i++) {
	    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);
	    int first_pdu;

	    for(first_pdu = 1; first_pdu || !opt_onepdu; first_pdu = 0) {
		/*
		 * Decode the encoded structure from file.
		 */
		structure = data_decode_from_file(pduType,
				file, name, suggested_bufsize, first_pdu);
		if(!structure) {
			if(errno) {
				/* Error message is already printed */
				exit(EX_DATAERR);
			} else {
				/* EOF */
				break;
			}
		}

		/* Check ASN.1 constraints */
		if(opt_check) {
			char errbuf[128];
			size_t errlen = sizeof(errbuf);
			if(asn_check_constraints(pduType, structure,
				errbuf, &errlen)) {
				fprintf(stderr, "%s: ASN.1 constraint "
					"check failed: %s\n", name, errbuf);
				exit(EX_DATAERR);
			}
		}

		switch(oform) {
		case OUT_NULL:
#ifdef	JUNKTEST
		    if(opt_jprob == 0.0)
#endif
			fprintf(stderr, "%s: decoded successfully\n", name);
			break;
		case OUT_TEXT:	/* -otext */
			asn_fprint(stdout, pduType, structure);
			break;
		case OUT_XER:	/* -oxer */
			if(xer_fprint(stdout, pduType, structure)) {
				fprintf(stderr,
					"%s: Cannot convert %s into XML\n",
					name, pduType->name);
				exit(EX_UNAVAILABLE);
			}
			break;
		case OUT_DER:
			erv = der_encode(pduType, structure, write_out, stdout);
			if(erv.encoded < 0) {
				fprintf(stderr,
					"%s: Cannot convert %s into DER\n",
					name, pduType->name);
				exit(EX_UNAVAILABLE);
			}
			DEBUG("Encoded in %ld bytes of DER", (long)erv.encoded);
			break;
		case OUT_PER:
			erv = uper_encode(pduType, structure, write_out, stdout);
			if(erv.encoded < 0) {
				fprintf(stderr,
				"%s: Cannot convert %s into Unaligned PER\n",
					name, pduType->name);
				exit(EX_UNAVAILABLE);
			}
			DEBUG("Encoded in %ld bits of UPER", (long)erv.encoded);
			break;
		}

		ASN_STRUCT_FREE(*pduType, structure);
		structure = NULL;
	    }

	    if(file && file != stdin)
		fclose(file);
	  }
	}

#ifdef	JUNKTEST
	if(opt_jprob > 0.0) {
		fprintf(stderr, "Junked %f OK (%d/%d)\n",
			opt_jprob, junk_failures, number_of_iterations);
	}
#endif	/* JUNKTEST */

	return 0;
}
Beispiel #11
0
static PDU_t *
load_object_from(enum expectation expectation, char *fbuf, int size, enum der_or_xer how) {
	asn_dec_rval_t rval;
	asn_dec_rval_t (*zer_decode)(struct asn_codec_ctx_s *,
		asn_TYPE_descriptor_t *, void **, const void *, size_t);
	PDU_t *st = 0;
	int csize = 1;

	if(how == AS_DER)
		zer_decode = ber_decode;
	else
		zer_decode = xer_decode;

	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, chunks %d\n",
			size, 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");
			}
			rval = zer_decode(0, &asn_DEF_PDU, (void **)&st,
				fbuf + fbuf_offset,
					fbuf_chunk < fbuf_left 
					? fbuf_chunk : fbuf_left);
			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_DER) {
				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;
}
Beispiel #12
0
static void
check(int is_ok, uint8_t *buf, size_t size, size_t consumed) {
	T1_t t, *tp;
	void *tpp = &tp;
	asn_dec_rval_t rval;
	asn_enc_rval_t erval;
	int ret;
	int i;

	tp = memset(&t, 0, sizeof(t));

	fprintf(stderr, "Buf %p\n", buf);
	rval = ber_decode(0, &asn_DEF_T1, (void **)tpp, buf, size);
	fprintf(stderr, "Returned code %d, consumed %d\n",
		(int)rval.code, (int)rval.consumed);

	if(is_ok) {
		assert(rval.code == RC_OK);
		assert(rval.consumed == (size_t)consumed);
		assert(t.a.size == 2);
		assert(t.b.present == b_PR_n);
		assert(t.b.choice.n.size == 1);
		assert(t.b.choice.n.buf[0] == 'i');
		assert(t.c.size == 1);
		assert(t.c.buf[0] == 'x');

	} else {
		if(rval.code == RC_OK) {
			assert(t.a.size != 2
				|| t.b.present != b_PR_n
				|| t.b.choice.n.size != 1
				|| t.c.size != 1
			);
		}
		assert(rval.consumed <= (size_t)consumed);
		ASN_STRUCT_RESET(asn_DEF_T1, tp);
		return;
	}

	fprintf(stderr, "=> Re-creating using DER encoder <=\n");

	/*
	 * Try to re-create using DER encoding.
	 */
	buf2_pos = 0;
	erval = der_encode(&asn_DEF_T1, tp, buf2_fill, 0);
	assert(erval.encoded != -1);
	if(erval.encoded != sizeof(buf1)) {
		printf("%d != %d\n", (int)erval.encoded, (int)sizeof(buf1));
	}
	assert(erval.encoded == (ssize_t)sizeof(buf1));
	for(i = 0; i < (ssize_t)sizeof(buf1); i++) {
		if(buf1[i] != buf2[i]) {
			fprintf(stderr, "Recreated buffer content mismatch:\n");
			fprintf(stderr, "Byte %d, %x != %x (%d != %d)\n",
				i,
				buf1[i], buf2[i],
				buf1[i], buf2[i]
			);
		}
		assert(buf1[i] == buf2[i]);
	}

	fprintf(stderr, "=== asn_fprint() ===\n");
	ret = asn_fprint(stderr, &asn_DEF_T1, tp);
	assert(ret == 0);
	fprintf(stderr, "=== xer_fprint() ===\n");
	ret = xer_fprint(stderr, &asn_DEF_T1, tp);
	assert(ret == 0);
	fprintf(stderr, "=== EOF ===\n");

	ASN_STRUCT_RESET(asn_DEF_T1, tp);
}
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;
}