~ubuntu-branches/ubuntu/hardy/openswan/hardy-updates

« back to all changes in this revision

Viewing changes to lib/libopenswan/ttodata.c

  • Committer: Bazaar Package Importer
  • Author(s): Rene Mayrhofer
  • Date: 2005-01-27 16:10:11 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050127161011-idgybmyz3vwhpfiq
Tags: 2.3.0-2
Urgency HIGH due to security issue and problems with build-deps in sarge.
* Fix the security issue. Please see
  http://www.idefense.com/application/poi/display?id=190&
      type=vulnerabilities&flashstatus=false
  for more details. Thanks to Martin Schulze for informing me about
  this issue.
  Closes: #292458: Openswan XAUTH/PAM Buffer Overflow Vulnerability
* Added a Build-Dependency to lynx.
  Closes: #291143: openswan: FTBFS: Missing build dependency.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * convert from text form of arbitrary data (e.g., keys) to binary
 
3
 * Copyright (C) 2000  Henry Spencer.
 
4
 * 
 
5
 * This library is free software; you can redistribute it and/or modify it
 
6
 * under the terms of the GNU Library General Public License as published by
 
7
 * the Free Software Foundation; either version 2 of the License, or (at your
 
8
 * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
 
9
 * 
 
10
 * This library is distributed in the hope that it will be useful, but
 
11
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
12
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
 
13
 * License for more details.
 
14
 *
 
15
 * RCSID $Id: ttodata.c,v 1.12 2004/04/09 18:00:37 mcr Exp $
 
16
 */
 
17
#include "internal.h"
 
18
#include "openswan.h"
 
19
 
 
20
/* converters and misc */
 
21
static int unhex(const char *, char *, size_t);
 
22
static int unb64(const char *, char *, size_t);
 
23
static int untext(const char *, char *, size_t);
 
24
static const char *badch(const char *, int, char *, size_t);
 
25
 
 
26
/* internal error codes for converters */
 
27
#define SHORT   (-2)            /* internal buffer too short */
 
28
#define BADPAD  (-3)            /* bad base64 padding */
 
29
#define BADCH0  (-4)            /* invalid character 0 */
 
30
#define BADCH1  (-5)            /* invalid character 1 */
 
31
#define BADCH2  (-6)            /* invalid character 2 */
 
32
#define BADCH3  (-7)            /* invalid character 3 */
 
33
#define BADOFF(code) (BADCH0-(code))
 
34
 
 
35
/*
 
36
 - ttodatav - convert text to data, with verbose error reports
 
37
 * If some of this looks slightly odd, it's because it has changed
 
38
 * repeatedly (from the original atodata()) without a major rewrite.
 
39
 */
 
40
const char *                    /* NULL on success, else literal or errp */
 
41
ttodatav(src, srclen, base, dst, dstlen, lenp, errp, errlen, flags)
 
42
const char *src;
 
43
size_t srclen;                  /* 0 means apply strlen() */
 
44
int base;                       /* 0 means figure it out */
 
45
char *dst;                      /* need not be valid if dstlen is 0 */
 
46
size_t dstlen;
 
47
size_t *lenp;                   /* where to record length (NULL is nowhere) */
 
48
char *errp;                     /* error buffer */
 
49
size_t errlen;
 
50
unsigned int flags;
 
51
{
 
52
        size_t ingroup; /* number of input bytes converted at once */
 
53
        char buf[4];            /* output from conversion */
 
54
        int nbytes;             /* size of output */
 
55
        int (*decode)(const char *, char *, size_t);
 
56
        char *stop;
 
57
        int ndone;
 
58
        int i;
 
59
        int underscoreok;
 
60
        int skipSpace = 0;
 
61
 
 
62
        if (srclen == 0)
 
63
                srclen = strlen(src);
 
64
        if (dstlen == 0)
 
65
                dst = buf;      /* point it somewhere valid */
 
66
        stop = dst + dstlen;
 
67
 
 
68
        if (base == 0) {
 
69
                if (srclen < 2)
 
70
                        return "input too short to be valid";
 
71
                if (*src++ != '0')
 
72
                        return "input does not begin with format prefix";
 
73
                switch (*src++) {
 
74
                case 'x':
 
75
                case 'X':
 
76
                        base = 16;
 
77
                        break;
 
78
                case 's':
 
79
                case 'S':
 
80
                        base = 64;
 
81
                        break;
 
82
                case 't':
 
83
                case 'T':
 
84
                        base = 256;
 
85
                        break;
 
86
                default:
 
87
                        return "unknown format prefix";
 
88
                }
 
89
                srclen -= 2;
 
90
        }
 
91
        switch (base) {
 
92
        case 16:
 
93
                decode = unhex;
 
94
                underscoreok = 1;
 
95
                ingroup = 2;
 
96
                break;
 
97
        case 64:
 
98
                decode = unb64;
 
99
                underscoreok = 0;
 
100
                ingroup = 4;
 
101
                if(flags & TTODATAV_IGNORESPACE) {
 
102
                        skipSpace = 1;
 
103
                }
 
104
                break;
 
105
 
 
106
        case 256:
 
107
                decode = untext;
 
108
                ingroup = 1;
 
109
                underscoreok = 0;
 
110
                break;
 
111
        default:
 
112
                return "unknown base";
 
113
        }
 
114
 
 
115
        /* proceed */
 
116
        ndone = 0;
 
117
        while (srclen > 0) {
 
118
                char stage[4];  /* staging area for group */
 
119
                size_t sl = 0;
 
120
 
 
121
                /* Grab ingroup characters into stage,
 
122
                 * squeezing out blanks if we are supposed to ignore them.
 
123
                 */
 
124
                for (sl = 0; sl < ingroup; src++, srclen--) {
 
125
                        if (srclen == 0)
 
126
                                return "input ends in mid-byte, perhaps truncated";
 
127
                        else if (!(skipSpace && (*src == ' ' || *src == '\t')))
 
128
                                stage[sl++] = *src;
 
129
                }
 
130
                
 
131
                nbytes = (*decode)(stage, buf, sizeof(buf));
 
132
                switch (nbytes) {
 
133
                case BADCH0:
 
134
                case BADCH1:
 
135
                case BADCH2:
 
136
                case BADCH3:
 
137
                        return badch(stage, nbytes, errp, errlen);
 
138
                case SHORT:
 
139
                        return "internal buffer too short (\"can't happen\")";
 
140
                case BADPAD:
 
141
                        return "bad (non-zero) padding at end of base64 input";
 
142
                }
 
143
                if (nbytes <= 0)
 
144
                        return "unknown internal error";
 
145
                for (i = 0; i < nbytes; i++) {
 
146
                        if (dst < stop)
 
147
                                *dst++ = buf[i];
 
148
                        ndone++;
 
149
                }
 
150
                while (srclen >= 1 && skipSpace && (*src == ' ' || *src == '\t')){
 
151
                        src++;
 
152
                        srclen--;
 
153
                }
 
154
                if (underscoreok && srclen > 1 && *src == '_') {
 
155
                        /* srclen > 1 means not last character */
 
156
                        src++;
 
157
                        srclen--;
 
158
                }
 
159
        }
 
160
 
 
161
        if (ndone == 0)
 
162
                return "no data bytes specified by input";
 
163
        if (lenp != NULL)
 
164
                *lenp = ndone;
 
165
        return NULL;
 
166
}
 
167
 
 
168
/*
 
169
 - ttodata - convert text to data
 
170
 */
 
171
const char *                    /* NULL on success, else literal */
 
172
ttodata(src, srclen, base, dst, dstlen, lenp)
 
173
const char *src;
 
174
size_t srclen;                  /* 0 means apply strlen() */
 
175
int base;                       /* 0 means figure it out */
 
176
char *dst;                      /* need not be valid if dstlen is 0 */
 
177
size_t dstlen;
 
178
size_t *lenp;                   /* where to record length (NULL is nowhere) */
 
179
{
 
180
        return ttodatav(src, srclen, base, dst, dstlen, lenp, (char *)NULL,
 
181
                        (size_t)0, TTODATAV_SPACECOUNTS);
 
182
}
 
183
 
 
184
/*
 
185
 - atodata - convert ASCII to data
 
186
 * backward-compatibility interface
 
187
 */
 
188
size_t                          /* 0 for failure, true length for success */
 
189
atodata(src, srclen, dst, dstlen)
 
190
const char *src;
 
191
size_t srclen;
 
192
char *dst;
 
193
size_t dstlen;
 
194
{
 
195
        size_t len;
 
196
        const char *err;
 
197
 
 
198
        err = ttodata(src, srclen, 0, dst, dstlen, &len);
 
199
        if (err != NULL)
 
200
                return 0;
 
201
        return len;
 
202
}
 
203
 
 
204
/*
 
205
 - atobytes - convert ASCII to data bytes
 
206
 * another backward-compatibility interface
 
207
 */
 
208
const char *
 
209
atobytes(src, srclen, dst, dstlen, lenp)
 
210
const char *src;
 
211
size_t srclen;
 
212
char *dst;
 
213
size_t dstlen;
 
214
size_t *lenp;
 
215
{
 
216
        return ttodata(src, srclen, 0, dst, dstlen, lenp);
 
217
}
 
218
 
 
219
/*
 
220
 - unhex - convert two ASCII hex digits to byte
 
221
 */
 
222
static int              /* number of result bytes, or error code */
 
223
unhex(src, dst, dstlen)
 
224
const char *src;        /* known to be full length */
 
225
char *dst;
 
226
size_t dstlen;          /* not large enough is a failure */
 
227
{
 
228
        char *p;
 
229
        unsigned byte;
 
230
        static char hex[] = "0123456789abcdef";
 
231
 
 
232
        if (dstlen < 1)
 
233
                return SHORT;
 
234
        
 
235
        p = strchr(hex, *src);
 
236
        if (p == NULL)
 
237
                p = strchr(hex, tolower(*src));
 
238
        if (p == NULL)
 
239
                return BADCH0;
 
240
        byte = (p - hex) << 4;
 
241
        src++;
 
242
 
 
243
        p = strchr(hex, *src);
 
244
        if (p == NULL)
 
245
                p = strchr(hex, tolower(*src));
 
246
        if (p == NULL)
 
247
                return BADCH1;
 
248
        byte |= (p - hex);
 
249
 
 
250
        *dst = byte;
 
251
        return 1;
 
252
}
 
253
 
 
254
/*
 
255
 - unb64 - convert four ASCII base64 digits to three bytes
 
256
 * Note that a base64 digit group is padded out with '=' if it represents
 
257
 * less than three bytes:  one byte is dd==, two is ddd=, three is dddd.
 
258
 */
 
259
static int              /* number of result bytes, or error code */
 
260
unb64(src, dst, dstlen)
 
261
const char *src;        /* known to be full length */
 
262
char *dst;
 
263
size_t dstlen;
 
264
{
 
265
        char *p;
 
266
        unsigned byte1;
 
267
        unsigned byte2;
 
268
        static char base64[] =
 
269
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
270
 
 
271
        if (dstlen < 3)
 
272
                return SHORT;
 
273
 
 
274
        p = strchr(base64, *src++);
 
275
 
 
276
        if (p == NULL)
 
277
                return BADCH0;
 
278
        byte1 = (p - base64) << 2;      /* first six bits */
 
279
 
 
280
        p = strchr(base64, *src++);
 
281
        if (p == NULL) {
 
282
                return BADCH1;
 
283
        }
 
284
 
 
285
        byte2 = p - base64;             /* next six:  two plus four */
 
286
        *dst++ = byte1 | (byte2 >> 4);
 
287
        byte1 = (byte2 & 0xf) << 4;
 
288
 
 
289
        p = strchr(base64, *src++);
 
290
        if (p == NULL) {
 
291
                if (*(src-1) == '=' && *src == '=') {
 
292
                        if (byte1 != 0)         /* bad padding */
 
293
                                return BADPAD;
 
294
                        return 1;
 
295
                }
 
296
                return BADCH2;
 
297
        }
 
298
 
 
299
        byte2 = p - base64;             /* next six:  four plus two */
 
300
        *dst++ = byte1 | (byte2 >> 2);
 
301
        byte1 = (byte2 & 0x3) << 6;
 
302
 
 
303
        p = strchr(base64, *src++);
 
304
        if (p == NULL) {
 
305
                if (*(src-1) == '=') {
 
306
                        if (byte1 != 0)         /* bad padding */
 
307
                                return BADPAD;
 
308
                        return 2;
 
309
                }
 
310
                return BADCH3;
 
311
        }
 
312
        byte2 = p - base64;             /* last six */
 
313
        *dst++ = byte1 | byte2;
 
314
 
 
315
        return 3;
 
316
}
 
317
 
 
318
/*
 
319
 - untext - convert one ASCII character to byte
 
320
 */
 
321
static int              /* number of result bytes, or error code */
 
322
untext(src, dst, dstlen)
 
323
const char *src;        /* known to be full length */
 
324
char *dst;
 
325
size_t dstlen;          /* not large enough is a failure */
 
326
{
 
327
        if (dstlen < 1)
 
328
                return SHORT;
 
329
 
 
330
        *dst = *src;
 
331
        return 1;
 
332
}
 
333
 
 
334
/*
 
335
 - badch - produce a nice complaint about an unknown character
 
336
 *
 
337
 * If the compiler complains that the array bigenough[] has a negative
 
338
 * size, that means the TTODATAV_BUF constant has been set too small.
 
339
 */
 
340
static const char *             /* literal or errp */
 
341
badch(src, errcode, errp, errlen)
 
342
const char *src;
 
343
int errcode;
 
344
char *errp;                     /* might be NULL */
 
345
size_t errlen;
 
346
{
 
347
        static const char pre[] = "unknown character (`";
 
348
        static const char suf[] = "') in input";
 
349
        char buf[5];
 
350
#       define  REQD    (sizeof(pre) - 1 + sizeof(buf) - 1 + sizeof(suf))
 
351
        struct sizecheck {
 
352
                char bigenough[TTODATAV_BUF - REQD];    /* see above */
 
353
        };
 
354
        char ch;
 
355
 
 
356
        if (errp == NULL || errlen < REQD)
 
357
                return "unknown character in input";
 
358
        strcpy(errp, pre);
 
359
        ch = *(src + BADOFF(errcode));
 
360
        if (isprint(ch)) {
 
361
                buf[0] = ch;
 
362
                buf[1] = '\0';
 
363
        } else {
 
364
                buf[0] = '\\';
 
365
                buf[1] = ((ch & 0700) >> 6) + '0';
 
366
                buf[2] = ((ch & 0070) >> 3) + '0';
 
367
                buf[3] = ((ch & 0007) >> 0) + '0';
 
368
                buf[4] = '\0';
 
369
        }
 
370
        strcat(errp, buf);
 
371
        strcat(errp, suf);
 
372
        return (const char *)errp;
 
373
}
 
374
 
 
375
 
 
376
 
 
377
#ifdef TTODATA_MAIN
 
378
 
 
379
#include <stdio.h>
 
380
 
 
381
struct artab;
 
382
static void check(struct artab *r, char *buf, size_t n, err_t oops, int *status);
 
383
static void regress(char *pgm);
 
384
static void hexout(const char *s, size_t len, FILE *f);
 
385
 
 
386
/*
 
387
 - main - convert first argument to hex, or run regression
 
388
 */
 
389
int
 
390
main(int argc, char *argv[])
 
391
{
 
392
        char buf[1024];
 
393
        char buf2[1024];
 
394
        char err[512];
 
395
        size_t n;
 
396
        size_t i;
 
397
        char *p = buf;
 
398
        char *p2 = buf2;
 
399
        char *pgm = argv[0];
 
400
        const char *oops;
 
401
 
 
402
        if (argc < 2) {
 
403
                fprintf(stderr, "Usage: %s {0x<hex>|0s<base64>|-r}\n", pgm);
 
404
                exit(2);
 
405
        }
 
406
 
 
407
        if (strcmp(argv[1], "-r") == 0) {
 
408
                regress(pgm);   /* should not return */
 
409
                fprintf(stderr, "%s: regress() returned?!?\n", pgm);
 
410
                exit(1);
 
411
        }
 
412
 
 
413
        oops = ttodatav(argv[1], 0, 0, buf, sizeof(buf), &n,
 
414
                        err, sizeof(err), TTODATAV_IGNORESPACE);
 
415
        if (oops != NULL) {
 
416
                fprintf(stderr, "%s: ttodata error `%s' in `%s'\n", pgm,
 
417
                                                                oops, argv[1]);
 
418
                exit(1);
 
419
        }
 
420
 
 
421
        if (n > sizeof(buf)) {
 
422
                p = (char *)malloc((size_t)n);
 
423
                if (p == NULL) {
 
424
                        fprintf(stderr,
 
425
                                "%s: unable to malloc %d bytes for result\n",
 
426
                                pgm, n);
 
427
                        exit(1);
 
428
                }
 
429
                oops = ttodata(argv[1], 0, 0, p, n, &n);
 
430
                if (oops != NULL) {
 
431
                        fprintf(stderr, "%s: error `%s' in ttodata retry?!?\n",
 
432
                                                                pgm, oops);
 
433
                        exit(1);
 
434
                }
 
435
        }
 
436
 
 
437
        hexout(p, n, stdout);
 
438
        printf("\n");
 
439
 
 
440
        i = datatot(buf, n, 'h', buf2, sizeof(buf2));
 
441
        if (i == 0) {
 
442
                fprintf(stderr, "%s: datatot reports error in `%s'\n", pgm,
 
443
                                                                argv[1]);
 
444
                exit(1);
 
445
        }
 
446
 
 
447
        if (i > sizeof(buf2)) {
 
448
                p2 = (char *)malloc((size_t)i);
 
449
                if (p == NULL) {
 
450
                        fprintf(stderr,
 
451
                                "%s: unable to malloc %d bytes for result\n",
 
452
                                pgm, i);
 
453
                        exit(1);
 
454
                }
 
455
                i = datatot(buf, n, 'h', p2, i);
 
456
                if (i == 0) {
 
457
                        fprintf(stderr, "%s: error in datatoa retry?!?\n", pgm);
 
458
                        exit(1);
 
459
                }
 
460
        }
 
461
 
 
462
        printf("%s\n", p2);
 
463
 
 
464
        exit(0);
 
465
}
 
466
 
 
467
/*
 
468
 - hexout - output an arbitrary-length string in hex
 
469
 */
 
470
static void
 
471
hexout(s, len, f)
 
472
const char *s;
 
473
size_t len;
 
474
FILE *f;
 
475
{
 
476
        size_t i;
 
477
 
 
478
        fprintf(f, "0x");
 
479
        for (i = 0; i < len; i++)
 
480
                fprintf(f, "%02x", (unsigned char)s[i]);
 
481
}
 
482
 
 
483
struct artab {
 
484
        int base;
 
485
#           define IGNORESPACE_BIAS 1000
 
486
        char *ascii;            /* NULL for end */
 
487
        char *data;             /* NULL for error expected */
 
488
} atodatatab[] = {
 
489
        { 0, "",                        NULL, },
 
490
        { 0, "0",                       NULL, },
 
491
        { 0, "0x",              NULL, },
 
492
        { 0, "0xa",             NULL, },
 
493
        { 0, "0xab",            "\xab", },
 
494
        { 0, "0xabc",           NULL, },
 
495
        { 0, "0xabcd",          "\xab\xcd", },
 
496
        { 0, "0x0123456789",    "\x01\x23\x45\x67\x89", },
 
497
        { 0, "0x01x",           NULL, },
 
498
        { 0, "0xabcdef",                "\xab\xcd\xef", },
 
499
        { 0, "0xABCDEF",                "\xab\xcd\xef", },
 
500
        { 0, "0XaBc0eEd81f",    "\xab\xc0\xee\xd8\x1f", },
 
501
        { 0, "0XaBc0_eEd8",     "\xab\xc0\xee\xd8", },
 
502
        { 0, "0XaBc0_",         NULL, },
 
503
        { 0, "0X_aBc0",         NULL, },
 
504
        { 0, "0Xa_Bc0",         NULL, },
 
505
        { 16, "aBc0eEd8",       "\xab\xc0\xee\xd8", },
 
506
        { 0, "0s",              NULL, },
 
507
        { 0, "0sA",             NULL, },
 
508
        { 0, "0sBA",            NULL, },
 
509
        { 0, "0sCBA",           NULL, },
 
510
        { 0, "0sDCBA",          "\x0c\x20\x40", },
 
511
        { 0, "0SDCBA",          "\x0c\x20\x40", },
 
512
        { 0, "0sDA==",          "\x0c", },
 
513
        { 0, "0sDC==",          NULL, },
 
514
        { 0, "0sDCA=",          "\x0c\x20", },
 
515
        { 0, "0sDCB=",          NULL, },
 
516
        { 0, "0sDCAZ",          "\x0c\x20\x19", },
 
517
        { 0, "0sDCAa",          "\x0c\x20\x1a", },
 
518
        { 0, "0sDCAz",          "\x0c\x20\x33", },
 
519
        { 0, "0sDCA0",          "\x0c\x20\x34", },
 
520
        { 0, "0sDCA9",          "\x0c\x20\x3d", },
 
521
        { 0, "0sDCA+",          "\x0c\x20\x3e", },
 
522
        { 0, "0sDCA/",          "\x0c\x20\x3f", },
 
523
        { 0, "0sAbraCadabra+",  "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
 
524
        { IGNORESPACE_BIAS + 0, "0s AbraCadabra+",      "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
 
525
        { IGNORESPACE_BIAS + 0, "0sA braCadabra+",      "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
 
526
        { IGNORESPACE_BIAS + 0, "0sAb raCadabra+",      "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
 
527
        { IGNORESPACE_BIAS + 0, "0sAbr aCadabra+",      "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
 
528
        { IGNORESPACE_BIAS + 0, "0sAbra Cadabra+",      "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
 
529
        { IGNORESPACE_BIAS + 0, "0sAbraC adabra+",      "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
 
530
        { IGNORESPACE_BIAS + 0, "0sAbraCa dabra+",      "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
 
531
        { IGNORESPACE_BIAS + 0, "0sAbraCad abra+",      "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
 
532
        { IGNORESPACE_BIAS + 0, "0sAbraCada bra+",      "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
 
533
        { IGNORESPACE_BIAS + 0, "0sAbraCadab ra+",      "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
 
534
        { IGNORESPACE_BIAS + 0, "0sAbraCadabr a+",      "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
 
535
        { IGNORESPACE_BIAS + 0, "0sAbraCadabra +",      "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
 
536
        { IGNORESPACE_BIAS + 0, "0sAbraCadabra+ ",      "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
 
537
        { 0, "0t",              NULL, },
 
538
        { 0, "0tabc_xyz",               "abc_xyz", },
 
539
        { 256, "abc_xyz",               "abc_xyz", },
 
540
        { 0, NULL,              NULL, },
 
541
};
 
542
 
 
543
struct drtab {
 
544
        char *data;     /* input; NULL for end */
 
545
        char format;
 
546
        int buflen;     /* -1 means big buffer */
 
547
        int outlen;     /* -1 means strlen(ascii)+1 */
 
548
        char *ascii;    /* NULL for error expected */
 
549
} datatoatab[] = {
 
550
        { "",                   'x',    -1,     -1,     NULL, },
 
551
        { "",                   'X',    -1,     -1,     NULL, },
 
552
        { "",                   'n',    -1,     -1,     NULL, },
 
553
        { "0",                  'x',    -1,     -1,     "0x30", },
 
554
        { "0",                  'x',    0,      5,      "---", },
 
555
        { "0",                  'x',    1,      5,      "", },
 
556
        { "0",                  'x',    2,      5,      "0", },
 
557
        { "0",                  'x',    3,      5,      "0x", },
 
558
        { "0",                  'x',    4,      5,      "0x3", },
 
559
        { "0",                  'x',    5,      5,      "0x30", },
 
560
        { "0",                  'x',    6,      5,      "0x30", },
 
561
        { "\xab\xcd",           'x',    -1,     -1,     "0xabcd", },
 
562
        { "\x01\x23\x45\x67\x89",       'x',    -1,     -1,     "0x0123456789", },
 
563
        { "\xab\xcd\xef",               'x',    -1,     -1,     "0xabcdef", },
 
564
        { "\xab\xc0\xee\xd8\x1f",       'x',    -1,     -1,     "0xabc0eed81f", },
 
565
        { "\x01\x02",           'h',    -1,     -1,     "0x0102", },
 
566
        { "\x01\x02\x03\x04\x05\x06",   'h',    -1, -1, "0x01020304_0506", },
 
567
        { "\xab\xc0\xee\xd8\x1f",       16,     -1,     -1,     "abc0eed81f", },
 
568
        { "\x0c\x20\x40",               's',    -1,     -1,     "0sDCBA", },
 
569
        { "\x0c\x20\x40",               's',    0,      7,      "---", },
 
570
        { "\x0c\x20\x40",               's',    1,      7,      "", },
 
571
        { "\x0c\x20\x40",               's',    2,      7,      "0", },
 
572
        { "\x0c\x20\x40",               's',    3,      7,      "0s", },
 
573
        { "\x0c\x20\x40",               's',    4,      7,      "0sD", },
 
574
        { "\x0c\x20\x40",               's',    5,      7,      "0sDC", },
 
575
        { "\x0c\x20\x40",               's',    6,      7,      "0sDCB", },
 
576
        { "\x0c\x20\x40",               's',    7,      7,      "0sDCBA", },
 
577
        { "\x0c\x20\x40",               's',    8,      7,      "0sDCBA", },
 
578
        { "\x0c",                       's',    -1,     -1,     "0sDA==", },
 
579
        { "\x0c\x20",           's',    -1,     -1,     "0sDCA=", },
 
580
        { "\x0c\x20\x19",               's',    -1,     -1,     "0sDCAZ", },
 
581
        { "\x0c\x20\x1a",               's',    -1,     -1,     "0sDCAa", },
 
582
        { "\x0c\x20\x33",               's',    -1,     -1,     "0sDCAz", },
 
583
        { "\x0c\x20\x34",               's',    -1,     -1,     "0sDCA0", },
 
584
        { "\x0c\x20\x3d",               's',    -1,     -1,     "0sDCA9", },
 
585
        { "\x0c\x20\x3e",               's',    -1,     -1,     "0sDCA+", },
 
586
        { "\x0c\x20\x3f",               's',    -1,     -1,     "0sDCA/", },
 
587
        { "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", 's', -1, -1, "0sAbraCadabra+", },
 
588
        { "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", 64, -1, -1, "AbraCadabra+", },
 
589
        { NULL,                 'x',    -1,     -1,     NULL, },
 
590
};
 
591
 
 
592
/*
 
593
 - regress - regression-test ttodata() and datatot()
 
594
 */
 
595
static void
 
596
check(r, buf, n, oops, status)
 
597
struct artab *r;
 
598
char *buf;
 
599
size_t n;
 
600
err_t oops;
 
601
int *status;
 
602
{
 
603
        if (oops != NULL && r->data == NULL)
 
604
                {}                      /* error expected */
 
605
        else if (oops != NULL) {
 
606
                printf("`%s' gave error `%s', expecting %d `", r->ascii,
 
607
                                                oops, strlen(r->data));
 
608
                hexout(r->data, strlen(r->data), stdout);
 
609
                printf("'\n");
 
610
                *status = 1;
 
611
        } else if (r->data == NULL) {
 
612
                printf("`%s' gave %d `", r->ascii, n);
 
613
                hexout(buf, n, stdout);
 
614
                printf("', expecting error\n");
 
615
                *status = 1;
 
616
        } else if (n != strlen(r->data)) {
 
617
                printf("length wrong in `%s': got %d `", r->ascii, n);
 
618
                hexout(buf, n, stdout);
 
619
                printf("', expecting %d `", strlen(r->data));
 
620
                hexout(r->data, strlen(r->data), stdout);
 
621
                printf("'\n");
 
622
                *status = 1;
 
623
        } else if (memcmp(buf, r->data, n) != 0) {
 
624
                printf("`%s' gave %d `", r->ascii, n);
 
625
                hexout(buf, n, stdout);
 
626
                printf("', expecting %d `", strlen(r->data));
 
627
                hexout(r->data, strlen(r->data), stdout);
 
628
                printf("'\n");
 
629
                *status = 1;
 
630
        }
 
631
        fflush(stdout);
 
632
}
 
633
 
 
634
static void                     /* should not return at all, in fact */
 
635
regress(pgm)
 
636
char *pgm;
 
637
{
 
638
        struct artab *r;
 
639
        struct drtab *dr;
 
640
        char buf[100];
 
641
        size_t n;
 
642
        int status = 0;
 
643
 
 
644
        for (r = atodatatab; r->ascii != NULL; r++) {
 
645
                int base = r->base;
 
646
                int xbase = 0;
 
647
 
 
648
                if ((base == 0 || base == IGNORESPACE_BIAS + 0) && r->ascii[0] == '0') {
 
649
                        switch (r->ascii[1]) {
 
650
                        case 'x':
 
651
                        case 'X':
 
652
                                xbase = 16;
 
653
                                break;
 
654
                        case 's':
 
655
                        case 'S':
 
656
                                xbase = 64;
 
657
                                break;
 
658
                        case 't':
 
659
                        case 'T':
 
660
                                xbase = 256;
 
661
                                break;
 
662
                        }
 
663
                }
 
664
                
 
665
                if (base >= IGNORESPACE_BIAS) {
 
666
                        base = base - IGNORESPACE_BIAS;
 
667
                        check(r, buf, n, ttodatav(r->ascii, 0, base, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
 
668
                        if (xbase != 0)
 
669
                                check(r, buf, n, ttodatav(r->ascii+2, 0, xbase, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
 
670
                } else {
 
671
                        check(r, buf, n, ttodata(r->ascii, 0, base, buf, sizeof(buf), &n), &status);
 
672
                        if (base == 64 || xbase == 64)
 
673
                                check(r, buf, n, ttodatav(r->ascii, 0, base, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
 
674
                        if (xbase != 0) {
 
675
                                check(r, buf, n, ttodata(r->ascii+2, 0, xbase, buf, sizeof(buf), &n), &status);
 
676
                                if (base == 64 || xbase == 64)
 
677
                                        check(r, buf, n, ttodatav(r->ascii+2, 0, xbase, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
 
678
                        }
 
679
                }
 
680
        }
 
681
        for (dr = datatoatab; dr->data != NULL; dr++) {
 
682
                size_t should;
 
683
 
 
684
                strcpy(buf, "---");
 
685
                n = datatot(dr->data, strlen(dr->data), dr->format, buf,
 
686
                                (dr->buflen == -1) ? sizeof(buf) : dr->buflen);
 
687
                should = (dr->ascii == NULL) ? 0 : strlen(dr->ascii) + 1;
 
688
                if (dr->outlen != -1)
 
689
                        should = dr->outlen;
 
690
                if (n == 0 && dr->ascii == NULL)
 
691
                        {}                      /* error expected */
 
692
                else if (n == 0) {
 
693
                        printf("`");
 
694
                        hexout(dr->data, strlen(dr->data), stdout);
 
695
                        printf("' %c gave error, expecting %d `%s'\n",
 
696
                                dr->format, should, dr->ascii);
 
697
                        status = 1;
 
698
                } else if (dr->ascii == NULL) {
 
699
                        printf("`");
 
700
                        hexout(dr->data, strlen(dr->data), stdout);
 
701
                        printf("' %c gave %d `%.*s', expecting error\n",
 
702
                                dr->format, n, (int)n, buf);
 
703
                        status = 1;
 
704
                } else if (n != should) {
 
705
                        printf("length wrong in `");
 
706
                        hexout(dr->data, strlen(dr->data), stdout);
 
707
                        printf("': got %d `%s'", n, buf);
 
708
                        printf(", expecting %d `%s'\n", should, dr->ascii);
 
709
                        status = 1;
 
710
                } else if (strcmp(buf, dr->ascii) != 0) {
 
711
                        printf("`");
 
712
                        hexout(dr->data, strlen(dr->data), stdout);
 
713
                        printf("' gave %d `%s'", n, buf);
 
714
                        printf(", expecting %d `%s'\n", should, dr->ascii);
 
715
                        status = 1;
 
716
                }
 
717
                fflush(stdout);
 
718
        }
 
719
        exit(status);
 
720
}
 
721
 
 
722
#endif /* TTODATA_MAIN */