blob: f78ad826b6c8e86a43ef423ed4cbcb60d9374682 [file] [log] [blame]
Lev Walkin22b54552004-10-28 13:22:54 +00001/*
Lev Walkind0625682006-08-25 02:35:08 +00002 * Generic converter template for a selected ASN.1 type.
Lev Walkind19216f2017-08-04 03:02:57 -07003 * Copyright (c) 2005-2017 Lev Walkin <vlm@lionet.info>.
Lev Walkin8a4a06c2007-06-29 12:44:01 +00004 * All rights reserved.
Lev Walkin22b54552004-10-28 13:22:54 +00005 *
Lev Walkind0625682006-08-25 02:35:08 +00006 * To compile with your own ASN.1 type, please redefine the PDU as shown:
Lev Walkin22b54552004-10-28 13:22:54 +00007 *
Lev Walkind0625682006-08-25 02:35:08 +00008 * cc -DPDU=MyCustomType -o myDecoder.o -c converter-sample.c
Lev Walkin22b54552004-10-28 13:22:54 +00009 */
Lev Walkinfb35e082017-08-04 03:06:51 -070010#ifdef HAVE_CONFIG_H
Lev Walkin22b54552004-10-28 13:22:54 +000011#include <config.h>
12#endif
13#include <stdio.h>
14#include <sys/types.h>
Lev Walkinfb35e082017-08-04 03:06:51 -070015#include <stdlib.h> /* for atoi(3) */
16#include <unistd.h> /* for getopt(3) */
17#include <string.h> /* for strerror(3) */
18#include <sysexits.h> /* for EX_* exit codes */
19#include <errno.h> /* for errno */
Lev Walkin22b54552004-10-28 13:22:54 +000020
Lev Walkin00949562005-03-10 13:39:03 +000021#include <asn_application.h>
Lev Walkinfb35e082017-08-04 03:06:51 -070022#include <asn_internal.h> /* for ASN__DEFAULT_STACK_MAX */
Lev Walkin22b54552004-10-28 13:22:54 +000023
Lev Walkind0625682006-08-25 02:35:08 +000024/* Convert "Type" defined by -DPDU into "asn_DEF_Type" */
Lev Walkinfb35e082017-08-04 03:06:51 -070025#define ASN_DEF_PDU(t) asn_DEF_ ## t
26#define DEF_PDU_Type(t) ASN_DEF_PDU(t)
27#define PDU_Type DEF_PDU_Type(PDU)
Lev Walkind0625682006-08-25 02:35:08 +000028
Lev Walkinfb35e082017-08-04 03:06:51 -070029extern asn_TYPE_descriptor_t PDU_Type; /* ASN.1 type to be decoded */
30#ifdef ASN_PDU_COLLECTION /* Generated by asn1c: -pdu=... */
Lev Walkin59b176e2005-11-26 11:25:14 +000031extern asn_TYPE_descriptor_t *asn_pdu_collection[];
32#endif
Lev Walkin22b54552004-10-28 13:22:54 +000033
34/*
Lev Walkin00949562005-03-10 13:39:03 +000035 * Open file and parse its contens.
Lev Walkin22b54552004-10-28 13:22:54 +000036 */
Lev Walkin00949562005-03-10 13:39:03 +000037static void *data_decode_from_file(asn_TYPE_descriptor_t *asnTypeOfPDU,
Lev Walkinfb35e082017-08-04 03:06:51 -070038 FILE *file, const char *name, ssize_t suggested_bufsize, int first_pdu);
Lev Walkind1bfea62005-11-08 03:06:16 +000039static int write_out(const void *buffer, size_t size, void *key);
Lev Walkinc744a022006-09-15 18:33:25 +000040static FILE *argument_to_file(char *av[], int idx);
41static char *argument_to_name(char *av[], int idx);
Lev Walkin22b54552004-10-28 13:22:54 +000042
Lev Walkinfb35e082017-08-04 03:06:51 -070043 int opt_debug; /* -d (or -dd) */
44static int opt_check; /* -c (constraints checking) */
45static int opt_stack; /* -s (maximum stack size) */
46static int opt_nopad; /* -per-nopad (PER input is not padded) */
47static int opt_onepdu; /* -1 (decode single PDU) */
Lev Walkind1bfea62005-11-08 03:06:16 +000048
49/* Input data format selector */
50static enum input_format {
Lev Walkinfb35e082017-08-04 03:06:51 -070051 INP_BER, /* -iber: BER input */
52 INP_XER, /* -ixer: XER input */
53 INP_OER, /* -ioer: OER input */
54 INP_PER /* -iper: Unaligned PER input */
55} iform; /* -i<format> */
Lev Walkind1bfea62005-11-08 03:06:16 +000056
57/* Output data format selector */
58static enum output_format {
Lev Walkinfb35e082017-08-04 03:06:51 -070059 OUT_XER, /* -oxer: XER (XML) output */
60 OUT_DER, /* -oder: DER (BER) output */
61 OUT_OER, /* -ooer: Canonical OER output */
62 OUT_PER, /* -oper: Unaligned PER output */
63 OUT_TEXT, /* -otext: semi-structured text */
64 OUT_NULL /* -onull: No pretty-printing */
65} oform; /* -o<format> */
Lev Walkin22b54552004-10-28 13:22:54 +000066
Lev Walkinfb35e082017-08-04 03:06:51 -070067#ifdef JUNKTEST /* Enable -J <probability> */
68#define JUNKOPT "J:"
69static double opt_jprob; /* Junk bit probability */
Lev Walkin1f12da42006-09-24 19:47:07 +000070static int junk_failures;
71static void junk_bytes_with_probability(uint8_t *, size_t, double prob);
72#else
Lev Walkinfb35e082017-08-04 03:06:51 -070073#define JUNKOPT
Lev Walkin1f12da42006-09-24 19:47:07 +000074#endif
75
Lev Walkin1d9e8dd2005-12-07 05:46:03 +000076/* Debug output function */
77static inline void
78DEBUG(const char *fmt, ...) {
Lev Walkinfb35e082017-08-04 03:06:51 -070079 va_list ap;
80 if(!opt_debug) return;
81 fprintf(stderr, "AD: ");
82 va_start(ap, fmt);
83 vfprintf(stderr, fmt, ap);
84 va_end(ap);
85 fprintf(stderr, "\n");
Lev Walkin1d9e8dd2005-12-07 05:46:03 +000086}
Lev Walkin22b54552004-10-28 13:22:54 +000087
88int
Lev Walkinc744a022006-09-15 18:33:25 +000089main(int ac, char *av[]) {
Lev Walkin7bb9d5b2017-08-26 23:31:58 -070090 FILE *binary_out;
Lev Walkinfb35e082017-08-04 03:06:51 -070091 static asn_TYPE_descriptor_t *pduType = &PDU_Type;
92 ssize_t suggested_bufsize = 8192; /* close or equal to stdio buffer */
93 int number_of_iterations = 1;
94 int num;
95 int ch;
Lev Walkin22b54552004-10-28 13:22:54 +000096
Lev Walkinfb35e082017-08-04 03:06:51 -070097 /* Figure out if specialty decoder needs to be default */
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +080098 if(pduType->op->oer_decoder)
Lev Walkinfb35e082017-08-04 03:06:51 -070099 iform = INP_OER;
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800100 else if(pduType->op->uper_decoder)
Lev Walkinfb35e082017-08-04 03:06:51 -0700101 iform = INP_PER;
Lev Walkin59b176e2005-11-26 11:25:14 +0000102
Lev Walkinfb35e082017-08-04 03:06:51 -0700103 /*
104 * Pocess the command-line argments.
105 */
106 while((ch = getopt(ac, av, "i:o:1b:cdn:p:hs:" JUNKOPT)) != -1)
107 switch(ch) {
108 case 'i':
109 if(optarg[0] == 'b') { iform = INP_BER; break; }
110 if(optarg[0] == 'x') { iform = INP_XER; break; }
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800111 if(pduType->op->oer_decoder
Lev Walkin7e5ea1d2017-08-06 00:59:28 -0700112 && optarg[0] == 'o') { iform = INP_OER; break; }
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800113 if(pduType->op->uper_decoder
Lev Walkinfb35e082017-08-04 03:06:51 -0700114 && optarg[0] == 'p') { iform = INP_PER; break; }
115 fprintf(stderr, "-i<format>: '%s': improper format selector\n",
116 optarg);
117 exit(EX_UNAVAILABLE);
118 case 'o':
119 if(optarg[0] == 'd') { oform = OUT_DER; break; }
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800120 if(pduType->op->oer_encoder
Lev Walkinfb35e082017-08-04 03:06:51 -0700121 && optarg[0] == 'o') { oform = OUT_OER; break; }
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800122 if(pduType->op->uper_encoder
Lev Walkinfb35e082017-08-04 03:06:51 -0700123 && optarg[0] == 'p') { oform = OUT_PER; break; }
124 if(optarg[0] == 'x') { oform = OUT_XER; break; }
125 if(optarg[0] == 't') { oform = OUT_TEXT; break; }
126 if(optarg[0] == 'n') { oform = OUT_NULL; break; }
127 fprintf(stderr, "-o<format>: '%s': improper format selector\n",
128 optarg);
129 exit(EX_UNAVAILABLE);
130 case '1':
131 opt_onepdu = 1;
132 break;
133 case 'b':
134 suggested_bufsize = atoi(optarg);
135 if(suggested_bufsize < 1
136 || suggested_bufsize > 16 * 1024 * 1024) {
137 fprintf(stderr,
138 "-b %s: Improper buffer size (1..16M)\n",
139 optarg);
140 exit(EX_UNAVAILABLE);
141 }
142 break;
143 case 'c':
144 opt_check = 1;
145 break;
146 case 'd':
147 opt_debug++; /* Double -dd means ASN.1 debug */
148 break;
149 case 'n':
150 number_of_iterations = atoi(optarg);
151 if(number_of_iterations < 1) {
152 fprintf(stderr,
153 "-n %s: Improper iterations count\n", optarg);
154 exit(EX_UNAVAILABLE);
155 }
156 break;
157 case 'p':
158 if(strcmp(optarg, "er-nopad") == 0) {
159 opt_nopad = 1;
160 break;
161 }
162#ifdef ASN_PDU_COLLECTION
163 if(strcmp(optarg, "list") == 0) {
164 asn_TYPE_descriptor_t **pdu = asn_pdu_collection;
165 fprintf(stderr, "Available PDU types:\n");
166 for(; *pdu; pdu++) printf("%s\n", (*pdu)->name);
167 exit(0);
168 } else if(optarg[0] >= 'A' && optarg[0] <= 'Z') {
169 asn_TYPE_descriptor_t **pdu = asn_pdu_collection;
170 while(*pdu && strcmp((*pdu)->name, optarg)) pdu++;
171 if(*pdu) { pduType = *pdu; break; }
172 fprintf(stderr, "-p %s: Unrecognized PDU\n", optarg);
Lev Walkin7e5ea1d2017-08-06 00:59:28 -0700173 exit(EX_USAGE);
174 }
175#else /* Without -pdu=auto there's just a single type */
176 if(strcmp(optarg, "list") == 0) {
177 fprintf(stderr, "Available PDU types:\n");
178 printf("%s\n", pduType->name);
179 exit(0);
180 } else if(optarg[0] >= 'A' && optarg[0] <= 'Z') {
181 if(strcmp(optarg, pduType->name) == 0) {
182 break;
183 }
184 fprintf(stderr, "-p %s: Unrecognized PDU\n", optarg);
185 exit(EX_USAGE);
Lev Walkinfb35e082017-08-04 03:06:51 -0700186 }
187#endif /* ASN_PDU_COLLECTION */
188 fprintf(stderr, "-p %s: Unrecognized option\n", optarg);
189 exit(EX_UNAVAILABLE);
190 case 's':
191 opt_stack = atoi(optarg);
192 if(opt_stack < 0) {
193 fprintf(stderr,
194 "-s %s: Non-negative value expected\n",
195 optarg);
196 exit(EX_UNAVAILABLE);
197 }
198 break;
199#ifdef JUNKTEST
200 case 'J':
201 opt_jprob = strtod(optarg, 0);
202 if(opt_jprob <= 0.0 || opt_jprob > 1.0) {
203 fprintf(stderr,
204 "-J %s: Probability range 0..1 expected \n",
205 optarg);
206 exit(EX_UNAVAILABLE);
207 }
208 break;
209#endif /* JUNKTEST */
210 case 'h':
211 default:
212#ifdef ASN_CONVERTER_TITLE
213#define _AXS(x) #x
214#define _ASX(x) _AXS(x)
215 fprintf(stderr, "%s\n", _ASX(ASN_CONVERTER_TITLE));
Lev Walkin8a4a06c2007-06-29 12:44:01 +0000216#endif
Lev Walkinae0c3c22017-08-26 17:20:32 -0700217 fprintf(stderr, "Usage: %s [options] <datafile> ...\n", av[0]);
Lev Walkinfb35e082017-08-04 03:06:51 -0700218 fprintf(stderr, "Where options are:\n");
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800219 if(pduType->op->oer_decoder)
Lev Walkinfb35e082017-08-04 03:06:51 -0700220 fprintf(stderr,
221 " -ioer Input is in OER (Octet Encoding Rules)%s\n",
222 iform == INP_OER ? " (DEFAULT)" : "");
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800223 if(pduType->op->uper_decoder)
Lev Walkinfb35e082017-08-04 03:06:51 -0700224 fprintf(stderr,
225 " -iper Input is in Unaligned PER (Packed Encoding Rules)%s\n",
226 iform == INP_PER ? " (DEFAULT)" : "");
227 fprintf(stderr,
228 " -iber Input is in BER (Basic Encoding Rules)%s\n",
229 iform == INP_BER ? " (DEFAULT)" : "");
230 fprintf(stderr,
231 " -ixer Input is in XER (XML Encoding Rules)\n");
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800232 if(pduType->op->oer_encoder)
Lev Walkinfb35e082017-08-04 03:06:51 -0700233 fprintf(stderr,
234 " -ooer Output in Canonical OER (Octet Encoding Rules)\n");
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800235 if(pduType->op->uper_encoder)
Lev Walkinfb35e082017-08-04 03:06:51 -0700236 fprintf(stderr,
237 " -oper Output in Unaligned PER (Packed Encoding Rules)\n");
238 fprintf(stderr,
239 " -oder Output in DER (Distinguished Encoding Rules)\n"
240 " -oxer Output in XER (XML Encoding Rules) (DEFAULT)\n"
241 " -otext Output in plain semi-structured text (dump)\n"
242 " -onull Verify (decode) input, but do not output\n");
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800243 if(pduType->op->uper_decoder)
Lev Walkinfb35e082017-08-04 03:06:51 -0700244 fprintf(stderr,
245 " -per-nopad Assume PER PDUs are not padded (-iper)\n");
246#ifdef ASN_PDU_COLLECTION
247 fprintf(stderr,
248 " -p <PDU> Specify PDU type to decode\n"
249 " -p list List available PDUs\n");
250#endif /* ASN_PDU_COLLECTION */
251 fprintf(stderr,
252 " -1 Decode only the first PDU in file\n"
253 " -b <size> Set the i/o buffer size (default is %ld)\n"
254 " -c Check ASN.1 constraints after decoding\n"
255 " -d Enable debugging (-dd is even better)\n"
256 " -n <num> Process files <num> times\n"
257 " -s <size> Set the stack usage limit (default is %d)\n"
258#ifdef JUNKTEST
259 " -J <prob> Set random junk test bit garbaging probability\n"
Lev Walkin1f12da42006-09-24 19:47:07 +0000260#endif
Lev Walkinfb35e082017-08-04 03:06:51 -0700261 , (long)suggested_bufsize, ASN__DEFAULT_STACK_MAX);
262 exit(EX_USAGE);
263 }
Lev Walkin22b54552004-10-28 13:22:54 +0000264
Lev Walkinfb35e082017-08-04 03:06:51 -0700265 ac -= optind;
266 av += optind;
Lev Walkin22b54552004-10-28 13:22:54 +0000267
Lev Walkinfb35e082017-08-04 03:06:51 -0700268 if(ac < 1) {
269 fprintf(stderr, "%s: No input files specified. "
270 "Try '-h' for more information\n",
271 av[-optind]);
272 exit(EX_USAGE);
273 }
Lev Walkin22b54552004-10-28 13:22:54 +0000274
Lev Walkin7bb9d5b2017-08-26 23:31:58 -0700275 if(isatty(1)) {
276 const int is_text_output = oform == OUT_TEXT || oform == OUT_XER;
277 if(is_text_output) {
278 binary_out = stdout;
279 } else {
280 fprintf(stderr, "(Suppressing binary output to a terminal.)\n");
281 binary_out = fopen("/dev/null", "wb");
282 if(!binary_out) {
283 fprintf(stderr, "Can't open /dev/null: %s\n", strerror(errno));
284 exit(EX_OSERR);
285 }
286 }
287 } else {
288 binary_out = stdout;
289 }
Lev Walkinfb35e082017-08-04 03:06:51 -0700290 setvbuf(stdout, 0, _IOLBF, 0);
Lev Walkin22b54552004-10-28 13:22:54 +0000291
Lev Walkinfb35e082017-08-04 03:06:51 -0700292 for(num = 0; num < number_of_iterations; num++) {
293 int ac_i;
294 /*
295 * Process all files in turn.
296 */
297 for(ac_i = 0; ac_i < ac; ac_i++) {
298 asn_enc_rval_t erv;
299 void *structure; /* Decoded structure */
300 FILE *file = argument_to_file(av, ac_i);
301 char *name = argument_to_name(av, ac_i);
302 int first_pdu;
Lev Walkin22b54552004-10-28 13:22:54 +0000303
Lev Walkinfb35e082017-08-04 03:06:51 -0700304 for(first_pdu = 1; first_pdu || !opt_onepdu; first_pdu = 0) {
305 /*
306 * Decode the encoded structure from file.
307 */
308 structure = data_decode_from_file(pduType, file, name,
309 suggested_bufsize, first_pdu);
310 if(!structure) {
311 if(errno) {
312 /* Error message is already printed */
313 exit(EX_DATAERR);
314 } else {
315 /* EOF */
316 break;
317 }
318 }
Lev Walkin22b54552004-10-28 13:22:54 +0000319
Lev Walkinfb35e082017-08-04 03:06:51 -0700320 /* Check ASN.1 constraints */
321 if(opt_check) {
322 char errbuf[128];
323 size_t errlen = sizeof(errbuf);
324 if(asn_check_constraints(pduType, structure, errbuf, &errlen)) {
325 fprintf(stderr,
326 "%s: ASN.1 constraint "
327 "check failed: %s\n",
328 name, errbuf);
329 exit(EX_DATAERR);
330 }
331 }
Lev Walkin22b54552004-10-28 13:22:54 +0000332
Lev Walkinfb35e082017-08-04 03:06:51 -0700333 switch(oform) {
334 case OUT_NULL:
335#ifdef JUNKTEST
336 if(opt_jprob == 0.0)
Lev Walkin1f12da42006-09-24 19:47:07 +0000337#endif
Lev Walkinfb35e082017-08-04 03:06:51 -0700338 fprintf(stderr, "%s: decoded successfully\n", name);
339 break;
340 case OUT_TEXT: /* -otext */
341 asn_fprint(stdout, pduType, structure);
342 break;
343 case OUT_XER: /* -oxer */
344 if(xer_fprint(stdout, pduType, structure)) {
345 fprintf(stderr, "%s: Cannot convert %s into XML\n", name,
346 pduType->name);
347 exit(EX_UNAVAILABLE);
348 }
349 break;
350 case OUT_DER:
Lev Walkin7bb9d5b2017-08-26 23:31:58 -0700351 erv = der_encode(pduType, structure, write_out, binary_out);
Lev Walkinfb35e082017-08-04 03:06:51 -0700352 if(erv.encoded < 0) {
353 fprintf(stderr, "%s: Cannot convert %s into DER\n", name,
354 pduType->name);
355 exit(EX_UNAVAILABLE);
356 }
357 DEBUG("Encoded in %ld bytes of DER", (long)erv.encoded);
358 break;
359 case OUT_OER:
Lev Walkin69033802017-08-25 12:15:58 -0700360#ifdef ASN_DISABLE_OER_SUPPORT
361 erv.encoded = -1;
362#else
Lev Walkin7bb9d5b2017-08-26 23:31:58 -0700363 erv = oer_encode(pduType, structure, write_out, binary_out);
Lev Walkin69033802017-08-25 12:15:58 -0700364#endif
Lev Walkinfb35e082017-08-04 03:06:51 -0700365 if(erv.encoded < 0) {
366 fprintf(stderr, "%s: Cannot convert %s into oER\n", name,
367 pduType->name);
368 exit(EX_UNAVAILABLE);
369 }
370 DEBUG("Encoded in %ld bytes of OER", (long)erv.encoded);
371 break;
372 case OUT_PER:
Lev Walkin69033802017-08-25 12:15:58 -0700373#ifdef ASN_DISABLE_PER_SUPPORT
374 erv.encoded = -1;
375#else
Lev Walkin7bb9d5b2017-08-26 23:31:58 -0700376 erv = uper_encode(pduType, structure, write_out, binary_out);
Lev Walkin69033802017-08-25 12:15:58 -0700377#endif
Lev Walkinfb35e082017-08-04 03:06:51 -0700378 if(erv.encoded < 0) {
379 fprintf(stderr,
380 "%s: Cannot convert %s into Unaligned PER\n", name,
381 pduType->name);
382 exit(EX_UNAVAILABLE);
383 }
384 DEBUG("Encoded in %ld bits of UPER", (long)erv.encoded);
385 break;
Lev Walkin7bb9d5b2017-08-26 23:31:58 -0700386 }
Lev Walkind1bfea62005-11-08 03:06:16 +0000387
Lev Walkin7bb9d5b2017-08-26 23:31:58 -0700388 ASN_STRUCT_FREE(*pduType, structure);
Lev Walkinfb35e082017-08-04 03:06:51 -0700389 }
Lev Walkinbc691772006-09-17 11:02:53 +0000390
Lev Walkinfb35e082017-08-04 03:06:51 -0700391 if(file && file != stdin) {
392 fclose(file);
393 }
394 }
395 }
Lev Walkin22b54552004-10-28 13:22:54 +0000396
Lev Walkinfb35e082017-08-04 03:06:51 -0700397#ifdef JUNKTEST
398 if(opt_jprob > 0.0) {
399 fprintf(stderr, "Junked %f OK (%d/%d)\n",
400 opt_jprob, junk_failures, number_of_iterations);
401 }
402#endif /* JUNKTEST */
Lev Walkin1f12da42006-09-24 19:47:07 +0000403
Lev Walkinfb35e082017-08-04 03:06:51 -0700404 return 0;
Lev Walkin22b54552004-10-28 13:22:54 +0000405}
406
Lev Walkin419f6752006-09-13 04:02:00 +0000407static struct dynamic_buffer {
Lev Walkinfb35e082017-08-04 03:06:51 -0700408 uint8_t *data; /* Pointer to the data bytes */
409 size_t offset; /* Offset from the start */
410 size_t length; /* Length of meaningful contents */
411 size_t unbits; /* Unused bits in the last byte */
412 size_t allocated; /* Allocated memory for data */
413 int nreallocs; /* Number of data reallocations */
414 off_t bytes_shifted; /* Number of bytes ever shifted */
Lev Walkin419f6752006-09-13 04:02:00 +0000415} DynamicBuffer;
Lev Walkin22b54552004-10-28 13:22:54 +0000416
Lev Walkin5a621d62006-09-18 20:05:34 +0000417static void
418buffer_dump() {
Lev Walkinfb35e082017-08-04 03:06:51 -0700419 uint8_t *p = DynamicBuffer.data + DynamicBuffer.offset;
420 uint8_t *e = p + DynamicBuffer.length - (DynamicBuffer.unbits ? 1 : 0);
421 if(!opt_debug) return;
422 DEBUG("Buffer: { d=%p, o=%ld, l=%ld, u=%ld, a=%ld, s=%ld }",
423 DynamicBuffer.data,
424 (long)DynamicBuffer.offset,
425 (long)DynamicBuffer.length,
426 (long)DynamicBuffer.unbits,
427 (long)DynamicBuffer.allocated,
428 (long)DynamicBuffer.bytes_shifted);
429 for(; p < e; p++) {
430 fprintf(stderr, " %c%c%c%c%c%c%c%c",
431 ((*p >> 7) & 1) ? '1' : '0',
432 ((*p >> 6) & 1) ? '1' : '0',
433 ((*p >> 5) & 1) ? '1' : '0',
434 ((*p >> 4) & 1) ? '1' : '0',
435 ((*p >> 3) & 1) ? '1' : '0',
436 ((*p >> 2) & 1) ? '1' : '0',
437 ((*p >> 1) & 1) ? '1' : '0',
438 ((*p >> 0) & 1) ? '1' : '0');
439 }
440 if(DynamicBuffer.unbits) {
441 unsigned int shift;
442 fprintf(stderr, " ");
443 for(shift = 7; shift >= DynamicBuffer.unbits; shift--)
444 fprintf(stderr, "%c", ((*p >> shift) & 1) ? '1' : '0');
445 fprintf(stderr, " %ld:%ld\n",
446 (long)DynamicBuffer.length - 1,
447 (long)8 - DynamicBuffer.unbits);
448 } else {
449 fprintf(stderr, " %ld\n", (long)DynamicBuffer.length);
450 }
Lev Walkin5a621d62006-09-18 20:05:34 +0000451}
452
453/*
454 * Move the buffer content left N bits, possibly joining it with
455 * preceeding content.
456 */
457static void
458buffer_shift_left(size_t offset, int bits) {
Lev Walkinfb35e082017-08-04 03:06:51 -0700459 uint8_t *ptr = DynamicBuffer.data + DynamicBuffer.offset + offset;
460 uint8_t *end = DynamicBuffer.data + DynamicBuffer.offset
461 + DynamicBuffer.length - 1;
462
463 if(!bits) return;
Lev Walkin5a621d62006-09-18 20:05:34 +0000464
Lev Walkinfb35e082017-08-04 03:06:51 -0700465 DEBUG("Shifting left %d bits off %ld (o=%ld, u=%ld, l=%ld)",
466 bits, (long)offset,
467 (long)DynamicBuffer.offset,
468 (long)DynamicBuffer.unbits,
469 (long)DynamicBuffer.length);
Lev Walkin5a621d62006-09-18 20:05:34 +0000470
Lev Walkinfb35e082017-08-04 03:06:51 -0700471 if(offset) {
472 int right;
473 right = ptr[0] >> (8 - bits);
Lev Walkin5a621d62006-09-18 20:05:34 +0000474
Lev Walkinfb35e082017-08-04 03:06:51 -0700475 DEBUG("oleft: %c%c%c%c%c%c%c%c",
476 ((ptr[-1] >> 7) & 1) ? '1' : '0',
477 ((ptr[-1] >> 6) & 1) ? '1' : '0',
478 ((ptr[-1] >> 5) & 1) ? '1' : '0',
479 ((ptr[-1] >> 4) & 1) ? '1' : '0',
480 ((ptr[-1] >> 3) & 1) ? '1' : '0',
481 ((ptr[-1] >> 2) & 1) ? '1' : '0',
482 ((ptr[-1] >> 1) & 1) ? '1' : '0',
483 ((ptr[-1] >> 0) & 1) ? '1' : '0');
Lev Walkin5a621d62006-09-18 20:05:34 +0000484
Lev Walkinfb35e082017-08-04 03:06:51 -0700485 DEBUG("oriht: %c%c%c%c%c%c%c%c",
486 ((ptr[0] >> 7) & 1) ? '1' : '0',
487 ((ptr[0] >> 6) & 1) ? '1' : '0',
488 ((ptr[0] >> 5) & 1) ? '1' : '0',
489 ((ptr[0] >> 4) & 1) ? '1' : '0',
490 ((ptr[0] >> 3) & 1) ? '1' : '0',
491 ((ptr[0] >> 2) & 1) ? '1' : '0',
492 ((ptr[0] >> 1) & 1) ? '1' : '0',
493 ((ptr[0] >> 0) & 1) ? '1' : '0');
Lev Walkin5a621d62006-09-18 20:05:34 +0000494
Lev Walkinfb35e082017-08-04 03:06:51 -0700495 DEBUG("mriht: %c%c%c%c%c%c%c%c",
496 ((right >> 7) & 1) ? '1' : '0',
497 ((right >> 6) & 1) ? '1' : '0',
498 ((right >> 5) & 1) ? '1' : '0',
499 ((right >> 4) & 1) ? '1' : '0',
500 ((right >> 3) & 1) ? '1' : '0',
501 ((right >> 2) & 1) ? '1' : '0',
502 ((right >> 1) & 1) ? '1' : '0',
503 ((right >> 0) & 1) ? '1' : '0');
Lev Walkin5a621d62006-09-18 20:05:34 +0000504
Lev Walkinfb35e082017-08-04 03:06:51 -0700505 ptr[-1] = (ptr[-1] & (0xff << bits)) | right;
Lev Walkin5a621d62006-09-18 20:05:34 +0000506
Lev Walkinfb35e082017-08-04 03:06:51 -0700507 DEBUG("after: %c%c%c%c%c%c%c%c",
508 ((ptr[-1] >> 7) & 1) ? '1' : '0',
509 ((ptr[-1] >> 6) & 1) ? '1' : '0',
510 ((ptr[-1] >> 5) & 1) ? '1' : '0',
511 ((ptr[-1] >> 4) & 1) ? '1' : '0',
512 ((ptr[-1] >> 3) & 1) ? '1' : '0',
513 ((ptr[-1] >> 2) & 1) ? '1' : '0',
514 ((ptr[-1] >> 1) & 1) ? '1' : '0',
515 ((ptr[-1] >> 0) & 1) ? '1' : '0');
516 }
Lev Walkin5a621d62006-09-18 20:05:34 +0000517
Lev Walkinfb35e082017-08-04 03:06:51 -0700518 buffer_dump();
Lev Walkin5a621d62006-09-18 20:05:34 +0000519
Lev Walkinfb35e082017-08-04 03:06:51 -0700520 for(; ptr < end; ptr++) {
521 int right = ptr[1] >> (8 - bits);
522 *ptr = (*ptr << bits) | right;
523 }
524 *ptr <<= bits;
Lev Walkin5a621d62006-09-18 20:05:34 +0000525
Lev Walkinfb35e082017-08-04 03:06:51 -0700526 DEBUG("Unbits [%d=>", (int)DynamicBuffer.unbits);
527 if(DynamicBuffer.unbits == 0) {
528 DynamicBuffer.unbits += bits;
529 } else {
530 DynamicBuffer.unbits += bits;
531 if(DynamicBuffer.unbits > 7) {
532 DynamicBuffer.unbits -= 8;
533 DynamicBuffer.length--;
534 DynamicBuffer.bytes_shifted++;
535 }
536 }
537 DEBUG("Unbits =>%d]", (int)DynamicBuffer.unbits);
Lev Walkin5a621d62006-09-18 20:05:34 +0000538
Lev Walkinfb35e082017-08-04 03:06:51 -0700539 buffer_dump();
Lev Walkin5a621d62006-09-18 20:05:34 +0000540
Lev Walkinfb35e082017-08-04 03:06:51 -0700541 DEBUG("Shifted. Now (o=%ld, u=%ld l=%ld)",
542 (long)DynamicBuffer.offset,
543 (long)DynamicBuffer.unbits,
544 (long)DynamicBuffer.length);
545
Lev Walkin5a621d62006-09-18 20:05:34 +0000546
547}
548
Lev Walkin22b54552004-10-28 13:22:54 +0000549/*
Lev Walkind1bfea62005-11-08 03:06:16 +0000550 * Ensure that the buffer contains at least this amount of free space.
Lev Walkin22b54552004-10-28 13:22:54 +0000551 */
Lev Walkin5a621d62006-09-18 20:05:34 +0000552static void add_bytes_to_buffer(const void *data2add, size_t bytes) {
Lev Walkin22b54552004-10-28 13:22:54 +0000553
Lev Walkinfb35e082017-08-04 03:06:51 -0700554 if(bytes == 0) return;
Lev Walkin5a621d62006-09-18 20:05:34 +0000555
Lev Walkinfb35e082017-08-04 03:06:51 -0700556 DEBUG("=> add_bytes(%ld) { o=%ld l=%ld u=%ld, s=%ld }",
557 (long)bytes,
558 (long)DynamicBuffer.offset,
559 (long)DynamicBuffer.length,
560 (long)DynamicBuffer.unbits,
561 (long)DynamicBuffer.allocated);
Lev Walkin22b54552004-10-28 13:22:54 +0000562
Lev Walkinfb35e082017-08-04 03:06:51 -0700563 if(DynamicBuffer.allocated
564 >= (DynamicBuffer.offset + DynamicBuffer.length + bytes)) {
565 DEBUG("\tNo buffer reallocation is necessary");
566 } else if(bytes <= DynamicBuffer.offset) {
567 DEBUG("\tContents shifted by %ld", DynamicBuffer.offset);
Lev Walkin22b54552004-10-28 13:22:54 +0000568
Lev Walkinfb35e082017-08-04 03:06:51 -0700569 /* Shift the buffer contents */
570 memmove(DynamicBuffer.data,
571 DynamicBuffer.data + DynamicBuffer.offset,
572 DynamicBuffer.length);
573 DynamicBuffer.bytes_shifted += DynamicBuffer.offset;
574 DynamicBuffer.offset = 0;
575 } else {
576 size_t newsize = (DynamicBuffer.allocated << 2) + bytes;
577 void *p = MALLOC(newsize);
578 if(!p) {
579 perror("malloc()");
580 exit(EX_OSERR);
581 }
582 memcpy(p,
583 DynamicBuffer.data + DynamicBuffer.offset,
584 DynamicBuffer.length);
585 FREEMEM(DynamicBuffer.data);
586 DynamicBuffer.data = (uint8_t *)p;
587 DynamicBuffer.offset = 0;
588 DynamicBuffer.allocated = newsize;
589 DynamicBuffer.nreallocs++;
590 DEBUG("\tBuffer reallocated to %ld (%d time)",
591 newsize, DynamicBuffer.nreallocs);
592 }
Lev Walkin1d9e8dd2005-12-07 05:46:03 +0000593
Lev Walkinfb35e082017-08-04 03:06:51 -0700594 memcpy(DynamicBuffer.data
595 + DynamicBuffer.offset + DynamicBuffer.length,
596 data2add, bytes);
597 DynamicBuffer.length += bytes;
598 if(DynamicBuffer.unbits) {
599 int bits = DynamicBuffer.unbits;
600 DynamicBuffer.unbits = 0;
601 buffer_shift_left(DynamicBuffer.length - bytes, bits);
602 }
Lev Walkin5a621d62006-09-18 20:05:34 +0000603
Lev Walkinfb35e082017-08-04 03:06:51 -0700604 DEBUG("<= add_bytes(%ld) { o=%ld l=%ld u=%ld, s=%ld }",
605 (long)bytes,
606 (long)DynamicBuffer.offset,
607 (long)DynamicBuffer.length,
608 (long)DynamicBuffer.unbits,
609 (long)DynamicBuffer.allocated);
Lev Walkin22b54552004-10-28 13:22:54 +0000610}
611
Lev Walkinc744a022006-09-15 18:33:25 +0000612static void *
Lev Walkinbc691772006-09-17 11:02:53 +0000613data_decode_from_file(asn_TYPE_descriptor_t *pduType, FILE *file, const char *name, ssize_t suggested_bufsize, int on_first_pdu) {
Lev Walkinfb35e082017-08-04 03:06:51 -0700614 static uint8_t *fbuf;
615 static ssize_t fbuf_size;
616 static asn_codec_ctx_t s_codec_ctx;
617 asn_codec_ctx_t *opt_codec_ctx = 0;
618 void *structure = 0;
619 asn_dec_rval_t rval;
620 size_t old_offset;
621 size_t new_offset;
622 int tolerate_eof;
623 size_t rd;
Lev Walkinc744a022006-09-15 18:33:25 +0000624
Lev Walkinfb35e082017-08-04 03:06:51 -0700625 if(!file) {
626 fprintf(stderr, "%s: %s\n", name, strerror(errno));
627 errno = EINVAL;
628 return 0;
629 }
Lev Walkin22b54552004-10-28 13:22:54 +0000630
Lev Walkinfb35e082017-08-04 03:06:51 -0700631 if(opt_stack) {
632 s_codec_ctx.max_stack_size = opt_stack;
633 opt_codec_ctx = &s_codec_ctx;
634 }
Lev Walkin22b54552004-10-28 13:22:54 +0000635
Lev Walkinfb35e082017-08-04 03:06:51 -0700636 DEBUG("Processing %s", name);
Lev Walkin22b54552004-10-28 13:22:54 +0000637
Lev Walkinfb35e082017-08-04 03:06:51 -0700638 /* prepare the file buffer */
639 if(fbuf_size != suggested_bufsize) {
640 fbuf = (uint8_t *)REALLOC(fbuf, suggested_bufsize);
641 if(!fbuf) {
642 perror("realloc()");
643 exit(EX_OSERR);
644 }
645 fbuf_size = suggested_bufsize;
646 }
Lev Walkin22b54552004-10-28 13:22:54 +0000647
Lev Walkinfb35e082017-08-04 03:06:51 -0700648 if(on_first_pdu) {
649 DynamicBuffer.offset = 0;
650 DynamicBuffer.length = 0;
651 DynamicBuffer.unbits = 0;
652 DynamicBuffer.allocated = 0;
653 DynamicBuffer.bytes_shifted = 0;
654 DynamicBuffer.nreallocs = 0;
655 }
Lev Walkinbc691772006-09-17 11:02:53 +0000656
Lev Walkinfb35e082017-08-04 03:06:51 -0700657 old_offset = DynamicBuffer.bytes_shifted + DynamicBuffer.offset;
Lev Walkin22b54552004-10-28 13:22:54 +0000658
Lev Walkinfb35e082017-08-04 03:06:51 -0700659 /* Pretend immediate EOF */
660 rval.code = RC_WMORE;
661 rval.consumed = 0;
Lev Walkind1bfea62005-11-08 03:06:16 +0000662
Lev Walkinfb35e082017-08-04 03:06:51 -0700663 for(tolerate_eof = 1; /* Allow EOF first time buffer is non-empty */
664 (rd = fread(fbuf, 1, fbuf_size, file))
665 || feof(file) == 0
666 || (tolerate_eof && DynamicBuffer.length)
667 ;) {
668 int ecbits = 0; /* Extra consumed bits in case of PER */
669 uint8_t *i_bptr;
670 size_t i_size;
Lev Walkin22b54552004-10-28 13:22:54 +0000671
Lev Walkinfb35e082017-08-04 03:06:51 -0700672 /*
673 * Copy the data over, or use the original buffer.
674 */
675 if(DynamicBuffer.allocated) {
676 /* Append new data into the existing dynamic buffer */
677 add_bytes_to_buffer(fbuf, rd);
678 i_bptr = DynamicBuffer.data + DynamicBuffer.offset;
679 i_size = DynamicBuffer.length;
680 } else {
681 i_bptr = fbuf;
682 i_size = rd;
683 }
Lev Walkin22b54552004-10-28 13:22:54 +0000684
Lev Walkinfb35e082017-08-04 03:06:51 -0700685 DEBUG("Decoding %ld bytes", (long)i_size);
Lev Walkinbc691772006-09-17 11:02:53 +0000686
Lev Walkinfb35e082017-08-04 03:06:51 -0700687#ifdef JUNKTEST
688 junk_bytes_with_probability(i_bptr, i_size, opt_jprob);
Lev Walkin1f12da42006-09-24 19:47:07 +0000689#endif
690
Lev Walkinfb35e082017-08-04 03:06:51 -0700691 switch(iform) {
692 case INP_BER:
693 rval = ber_decode(opt_codec_ctx, pduType,
694 (void **)&structure, i_bptr, i_size);
695 break;
696 case INP_OER:
Lev Walkin69033802017-08-25 12:15:58 -0700697#ifdef ASN_DISABLE_OER_SUPPORT
698 rval.code = RC_FAIL;
699 rval.consumed = 0;
700#else
Lev Walkinfb35e082017-08-04 03:06:51 -0700701 rval = oer_decode(opt_codec_ctx, pduType,
702 (void **)&structure, i_bptr, i_size);
Lev Walkin69033802017-08-25 12:15:58 -0700703#endif
Lev Walkinfb35e082017-08-04 03:06:51 -0700704 break;
705 case INP_XER:
706 rval = xer_decode(opt_codec_ctx, pduType,
707 (void **)&structure, i_bptr, i_size);
708 break;
709 case INP_PER:
Lev Walkin69033802017-08-25 12:15:58 -0700710#ifdef ASN_DISABLE_PER_SUPPORT
711 rval.code = RC_FAIL;
712 rval.consumed = 0;
713#else
Lev Walkinfb35e082017-08-04 03:06:51 -0700714 if(opt_nopad)
715 rval = uper_decode(opt_codec_ctx, pduType,
716 (void **)&structure, i_bptr, i_size, 0,
717 DynamicBuffer.unbits);
718 else
719 rval = uper_decode_complete(opt_codec_ctx, pduType,
720 (void **)&structure, i_bptr, i_size);
Lev Walkin69033802017-08-25 12:15:58 -0700721#endif
Lev Walkinfb35e082017-08-04 03:06:51 -0700722 switch(rval.code) {
723 case RC_OK:
724 /* Fall through */
725 case RC_FAIL:
726 if(opt_nopad) {
727 /* uper_decode() returns bits! */
728 /* Extra bits */
729 ecbits = rval.consumed % 8;
730 /* Convert into bytes! */
731 rval.consumed /= 8;
732 }
733 break;
734 case RC_WMORE:
735 /* PER does not support restartability */
736 ASN_STRUCT_FREE(*pduType, structure);
737 structure = 0;
738 rval.consumed = 0;
739 /* Continue accumulating data */
740 break;
741 }
742 break;
743 }
744 DEBUG("decode(%ld) consumed %ld+%db (%ld), code %d",
745 (long)DynamicBuffer.length,
746 (long)rval.consumed, ecbits, (long)i_size,
747 rval.code);
Lev Walkin22b54552004-10-28 13:22:54 +0000748
Lev Walkinfb35e082017-08-04 03:06:51 -0700749 if(DynamicBuffer.allocated == 0) {
750 /*
751 * Flush remainder into the intermediate buffer.
752 */
753 if(rval.code != RC_FAIL && rval.consumed < rd) {
754 add_bytes_to_buffer(fbuf + rval.consumed,
755 rd - rval.consumed);
756 buffer_shift_left(0, ecbits);
757 DynamicBuffer.bytes_shifted = rval.consumed;
758 rval.consumed = 0;
759 ecbits = 0;
760 }
761 }
Lev Walkin22b54552004-10-28 13:22:54 +0000762
Lev Walkinfb35e082017-08-04 03:06:51 -0700763 /*
764 * Adjust position inside the source buffer.
765 */
766 if(DynamicBuffer.allocated) {
767 DynamicBuffer.offset += rval.consumed;
768 DynamicBuffer.length -= rval.consumed;
769 } else {
770 DynamicBuffer.bytes_shifted += rval.consumed;
771 }
Lev Walkinbc691772006-09-17 11:02:53 +0000772
Lev Walkinfb35e082017-08-04 03:06:51 -0700773 switch(rval.code) {
774 case RC_OK:
775 if(ecbits) buffer_shift_left(0, ecbits);
776 DEBUG("RC_OK, finishing up with %ld+%d",
777 (long)rval.consumed, ecbits);
778 return structure;
779 case RC_WMORE:
780 DEBUG("RC_WMORE, continuing read=%ld, cons=%ld "
781 " with %ld..%ld-%ld..%ld",
782 (long)rd,
783 (long)rval.consumed,
784 (long)DynamicBuffer.offset,
785 (long)DynamicBuffer.length,
786 (long)DynamicBuffer.unbits,
787 (long)DynamicBuffer.allocated);
788 if(!rd) tolerate_eof--;
789 continue;
790 case RC_FAIL:
791 break;
792 }
793 break;
794 }
Lev Walkin22b54552004-10-28 13:22:54 +0000795
Lev Walkinfb35e082017-08-04 03:06:51 -0700796 DEBUG("Clean up partially decoded structure");
797 ASN_STRUCT_FREE(*pduType, structure);
Lev Walkin22b54552004-10-28 13:22:54 +0000798
Lev Walkinfb35e082017-08-04 03:06:51 -0700799 new_offset = DynamicBuffer.bytes_shifted + DynamicBuffer.offset;
Lev Walkinbc691772006-09-17 11:02:53 +0000800
Lev Walkinfb35e082017-08-04 03:06:51 -0700801 /*
802 * Print a message and return failure only if not EOF,
803 * unless this is our first PDU (empty file).
804 */
805 if(on_first_pdu
806 || DynamicBuffer.length
807 || new_offset - old_offset > ((iform == INP_XER)?sizeof("\r\n")-1:0)
808 ) {
Lev Walkin1f12da42006-09-24 19:47:07 +0000809
Lev Walkinfb35e082017-08-04 03:06:51 -0700810#ifdef JUNKTEST
811 /*
812 * Nothing's wrong with being unable to decode junk.
813 * Simulate EOF.
814 */
815 if(opt_jprob != 0.0) {
816 junk_failures++;
817 errno = 0;
818 return 0;
819 }
Lev Walkin1f12da42006-09-24 19:47:07 +0000820#endif
821
Lev Walkinfb35e082017-08-04 03:06:51 -0700822 DEBUG("ofp %d, no=%ld, oo=%ld, dbl=%ld",
823 on_first_pdu, (long)new_offset, (long)old_offset,
824 (long)DynamicBuffer.length);
825 fprintf(stderr, "%s: "
826 "Decode failed past byte %ld: %s\n",
827 name, (long)new_offset,
828 (rval.code == RC_WMORE)
829 ? "Unexpected end of input"
830 : "Input processing error");
831#ifndef ENOMSG
832#define ENOMSG EINVAL
Lev Walkin4bf96b92006-09-18 21:46:50 +0000833#endif
Lev Walkinfb35e082017-08-04 03:06:51 -0700834#ifndef EBADMSG
835#define EBADMSG EINVAL
Lev Walkin4bf96b92006-09-18 21:46:50 +0000836#endif
Lev Walkinfb35e082017-08-04 03:06:51 -0700837 errno = (rval.code == RC_WMORE) ? ENOMSG : EBADMSG;
838 } else {
839 /* Got EOF after a few successful PDUs */
840 errno = 0;
841 }
Lev Walkin22b54552004-10-28 13:22:54 +0000842
Lev Walkinfb35e082017-08-04 03:06:51 -0700843 return 0;
Lev Walkin22b54552004-10-28 13:22:54 +0000844}
845
Lev Walkin419f6752006-09-13 04:02:00 +0000846/* Dump the buffer out to the specified FILE */
847static int write_out(const void *buffer, size_t size, void *key) {
Lev Walkinfb35e082017-08-04 03:06:51 -0700848 FILE *fp = (FILE *)key;
849 return (fwrite(buffer, 1, size, fp) == size) ? 0 : -1;
Lev Walkin419f6752006-09-13 04:02:00 +0000850}
Lev Walkinc744a022006-09-15 18:33:25 +0000851
852static int argument_is_stdin(char *av[], int idx) {
Lev Walkinfb35e082017-08-04 03:06:51 -0700853 if(strcmp(av[idx], "-")) {
854 return 0; /* Certainly not <stdin> */
855 } else {
856 /* This might be <stdin>, unless `./program -- -` */
857 if(strcmp(av[-1], "--"))
858 return 1;
859 else
860 return 0;
861 }
Lev Walkinc744a022006-09-15 18:33:25 +0000862}
863
864static FILE *argument_to_file(char *av[], int idx) {
Lev Walkinfb35e082017-08-04 03:06:51 -0700865 return argument_is_stdin(av, idx) ? stdin : fopen(av[idx], "rb");
Lev Walkinc744a022006-09-15 18:33:25 +0000866}
867
868static char *argument_to_name(char *av[], int idx) {
Lev Walkinfb35e082017-08-04 03:06:51 -0700869 return argument_is_stdin(av, idx) ? "standard input" : av[idx];
Lev Walkinc744a022006-09-15 18:33:25 +0000870}
Lev Walkin1f12da42006-09-24 19:47:07 +0000871
Lev Walkinfb35e082017-08-04 03:06:51 -0700872#ifdef JUNKTEST
Lev Walkin1f12da42006-09-24 19:47:07 +0000873/*
874 * Fill bytes with some garbage with specified probability (more or less).
875 */
876static void
877junk_bytes_with_probability(uint8_t *buf, size_t size, double prob) {
Lev Walkinfb35e082017-08-04 03:06:51 -0700878 static int junkmode;
879 uint8_t *ptr;
880 uint8_t *end;
881 if(opt_jprob <= 0.0) return;
882 for(ptr = buf, end = ptr + size; ptr < end; ptr++) {
883 int byte = *ptr;
884 if(junkmode++ & 1) {
885 if((((double)random() / RAND_MAX) < prob))
886 byte = random() & 0xff;
887 } else {
888#define BPROB(b) ((((double)random() / RAND_MAX) < prob) ? b : 0)
889 byte ^= BPROB(0x80);
890 byte ^= BPROB(0x40);
891 byte ^= BPROB(0x20);
892 byte ^= BPROB(0x10);
893 byte ^= BPROB(0x08);
894 byte ^= BPROB(0x04);
895 byte ^= BPROB(0x02);
896 byte ^= BPROB(0x01);
897 }
898 if(byte != *ptr) {
899 DEBUG("Junk buf[%d] %02x -> %02x", ptr - buf, *ptr, byte);
900 *ptr = byte;
901 }
902 }
Lev Walkin1f12da42006-09-24 19:47:07 +0000903}
Lev Walkinfb35e082017-08-04 03:06:51 -0700904#endif /* JUNKTEST */
Lev Walkin1f12da42006-09-24 19:47:07 +0000905