Line data Source code
1 : /* crypto/bio/b_print.c */
2 : /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 : * All rights reserved.
4 : *
5 : * This package is an SSL implementation written
6 : * by Eric Young (eay@cryptsoft.com).
7 : * The implementation was written so as to conform with Netscapes SSL.
8 : *
9 : * This library is free for commercial and non-commercial use as long as
10 : * the following conditions are aheared to. The following conditions
11 : * apply to all code found in this distribution, be it the RC4, RSA,
12 : * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13 : * included with this distribution is covered by the same copyright terms
14 : * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 : *
16 : * Copyright remains Eric Young's, and as such any Copyright notices in
17 : * the code are not to be removed.
18 : * If this package is used in a product, Eric Young should be given attribution
19 : * as the author of the parts of the library used.
20 : * This can be in the form of a textual message at program startup or
21 : * in documentation (online or textual) provided with the package.
22 : *
23 : * Redistribution and use in source and binary forms, with or without
24 : * modification, are permitted provided that the following conditions
25 : * are met:
26 : * 1. Redistributions of source code must retain the copyright
27 : * notice, this list of conditions and the following disclaimer.
28 : * 2. Redistributions in binary form must reproduce the above copyright
29 : * notice, this list of conditions and the following disclaimer in the
30 : * documentation and/or other materials provided with the distribution.
31 : * 3. All advertising materials mentioning features or use of this software
32 : * must display the following acknowledgement:
33 : * "This product includes cryptographic software written by
34 : * Eric Young (eay@cryptsoft.com)"
35 : * The word 'cryptographic' can be left out if the rouines from the library
36 : * being used are not cryptographic related :-).
37 : * 4. If you include any Windows specific code (or a derivative thereof) from
38 : * the apps directory (application code) you must include an acknowledgement:
39 : * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 : *
41 : * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 : * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 : * SUCH DAMAGE.
52 : *
53 : * The licence and distribution terms for any publically available version or
54 : * derivative of this code cannot be changed. i.e. this code cannot simply be
55 : * copied and put under another distribution licence
56 : * [including the GNU Public Licence.]
57 : */
58 :
59 : /* disable assert() unless BIO_DEBUG has been defined */
60 : #ifndef BIO_DEBUG
61 : # ifndef NDEBUG
62 : # define NDEBUG
63 : # endif
64 : #endif
65 :
66 : /*
67 : * Stolen from tjh's ssl/ssl_trc.c stuff.
68 : */
69 :
70 : #include <stdio.h>
71 : #include <string.h>
72 : #include <ctype.h>
73 : #include <assert.h>
74 : #include <limits.h>
75 : #include "cryptlib.h"
76 : #ifndef NO_SYS_TYPES_H
77 : # include <sys/types.h>
78 : #endif
79 : #include <openssl/bn.h> /* To get BN_LLONG properly defined */
80 : #include <openssl/bio.h>
81 :
82 : #if defined(BN_LLONG) || defined(SIXTY_FOUR_BIT)
83 : # ifndef HAVE_LONG_LONG
84 : # define HAVE_LONG_LONG 1
85 : # endif
86 : #endif
87 :
88 : /***************************************************************************/
89 :
90 : /*
91 : * Copyright Patrick Powell 1995
92 : * This code is based on code written by Patrick Powell <papowell@astart.com>
93 : * It may be used for any purpose as long as this notice remains intact
94 : * on all source code distributions.
95 : */
96 :
97 : /*-
98 : * This code contains numerious changes and enhancements which were
99 : * made by lots of contributors over the last years to Patrick Powell's
100 : * original code:
101 : *
102 : * o Patrick Powell <papowell@astart.com> (1995)
103 : * o Brandon Long <blong@fiction.net> (1996, for Mutt)
104 : * o Thomas Roessler <roessler@guug.de> (1998, for Mutt)
105 : * o Michael Elkins <me@cs.hmc.edu> (1998, for Mutt)
106 : * o Andrew Tridgell <tridge@samba.org> (1998, for Samba)
107 : * o Luke Mewburn <lukem@netbsd.org> (1999, for LukemFTP)
108 : * o Ralf S. Engelschall <rse@engelschall.com> (1999, for Pth)
109 : * o ... (for OpenSSL)
110 : */
111 :
112 : #ifdef HAVE_LONG_DOUBLE
113 : # define LDOUBLE long double
114 : #else
115 : # define LDOUBLE double
116 : #endif
117 :
118 : #ifdef HAVE_LONG_LONG
119 : # if defined(_WIN32) && !defined(__GNUC__)
120 : # define LLONG __int64
121 : # else
122 : # define LLONG long long
123 : # endif
124 : #else
125 : # define LLONG long
126 : #endif
127 :
128 : static void fmtstr(char **, char **, size_t *, size_t *,
129 : const char *, int, int, int);
130 : static void fmtint(char **, char **, size_t *, size_t *,
131 : LLONG, int, int, int, int);
132 : static void fmtfp(char **, char **, size_t *, size_t *,
133 : LDOUBLE, int, int, int);
134 : static void doapr_outch(char **, char **, size_t *, size_t *, int);
135 : static void _dopr(char **sbuffer, char **buffer,
136 : size_t *maxlen, size_t *retlen, int *truncated,
137 : const char *format, va_list args);
138 :
139 : /* format read states */
140 : #define DP_S_DEFAULT 0
141 : #define DP_S_FLAGS 1
142 : #define DP_S_MIN 2
143 : #define DP_S_DOT 3
144 : #define DP_S_MAX 4
145 : #define DP_S_MOD 5
146 : #define DP_S_CONV 6
147 : #define DP_S_DONE 7
148 :
149 : /* format flags - Bits */
150 : #define DP_F_MINUS (1 << 0)
151 : #define DP_F_PLUS (1 << 1)
152 : #define DP_F_SPACE (1 << 2)
153 : #define DP_F_NUM (1 << 3)
154 : #define DP_F_ZERO (1 << 4)
155 : #define DP_F_UP (1 << 5)
156 : #define DP_F_UNSIGNED (1 << 6)
157 :
158 : /* conversion flags */
159 : #define DP_C_SHORT 1
160 : #define DP_C_LONG 2
161 : #define DP_C_LDOUBLE 3
162 : #define DP_C_LLONG 4
163 :
164 : /* some handy macros */
165 : #define char_to_int(p) (p - '0')
166 : #define OSSL_MAX(p,q) ((p >= q) ? p : q)
167 :
168 : static void
169 1480 : _dopr(char **sbuffer,
170 : char **buffer,
171 : size_t *maxlen,
172 : size_t *retlen, int *truncated, const char *format, va_list args)
173 : {
174 : char ch;
175 : LLONG value;
176 : LDOUBLE fvalue;
177 : char *strvalue;
178 : int min;
179 : int max;
180 : int state;
181 : int flags;
182 : int cflags;
183 : size_t currlen;
184 :
185 : state = DP_S_DEFAULT;
186 1480 : flags = currlen = cflags = min = 0;
187 : max = -1;
188 1480 : ch = *format++;
189 :
190 76960 : while (state != DP_S_DONE) {
191 74000 : if (ch == '\0' || (buffer == NULL && currlen >= *maxlen))
192 : state = DP_S_DONE;
193 :
194 74000 : switch (state) {
195 : case DP_S_DEFAULT:
196 10360 : if (ch == '%')
197 : state = DP_S_FLAGS;
198 : else
199 1480 : doapr_outch(sbuffer, buffer, &currlen, maxlen, ch);
200 10360 : ch = *format++;
201 10360 : break;
202 : case DP_S_FLAGS:
203 17760 : switch (ch) {
204 : case '-':
205 0 : flags |= DP_F_MINUS;
206 0 : ch = *format++;
207 0 : break;
208 : case '+':
209 0 : flags |= DP_F_PLUS;
210 0 : ch = *format++;
211 0 : break;
212 : case ' ':
213 0 : flags |= DP_F_SPACE;
214 0 : ch = *format++;
215 0 : break;
216 : case '#':
217 0 : flags |= DP_F_NUM;
218 0 : ch = *format++;
219 0 : break;
220 : case '0':
221 8880 : flags |= DP_F_ZERO;
222 8880 : ch = *format++;
223 8880 : break;
224 : default:
225 : state = DP_S_MIN;
226 : break;
227 : }
228 : break;
229 : case DP_S_MIN:
230 17760 : if (isdigit((unsigned char)ch)) {
231 8880 : min = 10 * min + char_to_int(ch);
232 8880 : ch = *format++;
233 8880 : } else if (ch == '*') {
234 0 : min = va_arg(args, int);
235 0 : ch = *format++;
236 : state = DP_S_DOT;
237 : } else
238 : state = DP_S_DOT;
239 : break;
240 : case DP_S_DOT:
241 8880 : if (ch == '.') {
242 : state = DP_S_MAX;
243 0 : ch = *format++;
244 : } else
245 : state = DP_S_MOD;
246 : break;
247 : case DP_S_MAX:
248 0 : if (isdigit((unsigned char)ch)) {
249 0 : if (max < 0)
250 : max = 0;
251 0 : max = 10 * max + char_to_int(ch);
252 0 : ch = *format++;
253 0 : } else if (ch == '*') {
254 0 : max = va_arg(args, int);
255 0 : ch = *format++;
256 : state = DP_S_MOD;
257 : } else
258 : state = DP_S_MOD;
259 : break;
260 : case DP_S_MOD:
261 8880 : switch (ch) {
262 : case 'h':
263 : cflags = DP_C_SHORT;
264 0 : ch = *format++;
265 0 : break;
266 : case 'l':
267 0 : if (*format == 'l') {
268 : cflags = DP_C_LLONG;
269 0 : format++;
270 : } else
271 : cflags = DP_C_LONG;
272 0 : ch = *format++;
273 0 : break;
274 : case 'q':
275 : cflags = DP_C_LLONG;
276 0 : ch = *format++;
277 0 : break;
278 : case 'L':
279 : cflags = DP_C_LDOUBLE;
280 0 : ch = *format++;
281 0 : break;
282 : default:
283 : break;
284 : }
285 : state = DP_S_CONV;
286 : break;
287 : case DP_S_CONV:
288 8880 : switch (ch) {
289 : case 'd':
290 : case 'i':
291 8880 : switch (cflags) {
292 : case DP_C_SHORT:
293 0 : value = (short int)va_arg(args, int);
294 0 : break;
295 : case DP_C_LONG:
296 0 : value = va_arg(args, long int);
297 0 : break;
298 : case DP_C_LLONG:
299 0 : value = va_arg(args, LLONG);
300 0 : break;
301 : default:
302 8880 : value = va_arg(args, int);
303 8880 : break;
304 : }
305 8880 : fmtint(sbuffer, buffer, &currlen, maxlen,
306 : value, 10, min, max, flags);
307 8880 : break;
308 : case 'X':
309 0 : flags |= DP_F_UP;
310 : /* FALLTHROUGH */
311 : case 'x':
312 : case 'o':
313 : case 'u':
314 0 : flags |= DP_F_UNSIGNED;
315 0 : switch (cflags) {
316 : case DP_C_SHORT:
317 0 : value = (unsigned short int)va_arg(args, unsigned int);
318 0 : break;
319 : case DP_C_LONG:
320 0 : value = (LLONG) va_arg(args, unsigned long int);
321 0 : break;
322 : case DP_C_LLONG:
323 0 : value = va_arg(args, unsigned LLONG);
324 0 : break;
325 : default:
326 0 : value = (LLONG) va_arg(args, unsigned int);
327 0 : break;
328 : }
329 0 : fmtint(sbuffer, buffer, &currlen, maxlen, value,
330 0 : ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
331 : min, max, flags);
332 0 : break;
333 : case 'f':
334 0 : if (cflags == DP_C_LDOUBLE)
335 0 : fvalue = va_arg(args, LDOUBLE);
336 : else
337 0 : fvalue = va_arg(args, double);
338 0 : fmtfp(sbuffer, buffer, &currlen, maxlen,
339 : fvalue, min, max, flags);
340 0 : break;
341 : case 'E':
342 : flags |= DP_F_UP;
343 : case 'e':
344 0 : if (cflags == DP_C_LDOUBLE)
345 0 : fvalue = va_arg(args, LDOUBLE);
346 : else
347 0 : fvalue = va_arg(args, double);
348 : break;
349 : case 'G':
350 : flags |= DP_F_UP;
351 : case 'g':
352 0 : if (cflags == DP_C_LDOUBLE)
353 0 : fvalue = va_arg(args, LDOUBLE);
354 : else
355 0 : fvalue = va_arg(args, double);
356 : break;
357 : case 'c':
358 0 : doapr_outch(sbuffer, buffer, &currlen, maxlen,
359 : va_arg(args, int));
360 0 : break;
361 : case 's':
362 0 : strvalue = va_arg(args, char *);
363 0 : if (max < 0) {
364 0 : if (buffer)
365 : max = INT_MAX;
366 : else
367 0 : max = *maxlen;
368 : }
369 0 : fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
370 : flags, min, max);
371 0 : break;
372 : case 'p':
373 0 : value = (long)va_arg(args, void *);
374 0 : fmtint(sbuffer, buffer, &currlen, maxlen,
375 : value, 16, min, max, flags | DP_F_NUM);
376 0 : break;
377 : case 'n': /* XXX */
378 0 : if (cflags == DP_C_SHORT) {
379 : short int *num;
380 0 : num = va_arg(args, short int *);
381 0 : *num = currlen;
382 0 : } else if (cflags == DP_C_LONG) { /* XXX */
383 : long int *num;
384 0 : num = va_arg(args, long int *);
385 0 : *num = (long int)currlen;
386 0 : } else if (cflags == DP_C_LLONG) { /* XXX */
387 : LLONG *num;
388 0 : num = va_arg(args, LLONG *);
389 0 : *num = (LLONG) currlen;
390 : } else {
391 : int *num;
392 0 : num = va_arg(args, int *);
393 0 : *num = currlen;
394 : }
395 : break;
396 : case '%':
397 0 : doapr_outch(sbuffer, buffer, &currlen, maxlen, ch);
398 0 : break;
399 : case 'w':
400 : /* not supported yet, treat as next char */
401 0 : ch = *format++;
402 0 : break;
403 : default:
404 : /* unknown, skip */
405 : break;
406 : }
407 8880 : ch = *format++;
408 : state = DP_S_DEFAULT;
409 : flags = cflags = min = 0;
410 : max = -1;
411 8880 : break;
412 : case DP_S_DONE:
413 : break;
414 : default:
415 : break;
416 : }
417 : }
418 1480 : *truncated = (currlen > *maxlen - 1);
419 1480 : if (*truncated)
420 0 : currlen = *maxlen - 1;
421 1480 : doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0');
422 1480 : *retlen = currlen - 1;
423 1480 : return;
424 : }
425 :
426 : static void
427 0 : fmtstr(char **sbuffer,
428 : char **buffer,
429 : size_t *currlen,
430 : size_t *maxlen, const char *value, int flags, int min, int max)
431 : {
432 : int padlen, strln;
433 : int cnt = 0;
434 :
435 0 : if (value == 0)
436 : value = "<NULL>";
437 0 : for (strln = 0; value[strln]; ++strln) ;
438 0 : padlen = min - strln;
439 0 : if (padlen < 0)
440 : padlen = 0;
441 0 : if (flags & DP_F_MINUS)
442 0 : padlen = -padlen;
443 :
444 0 : while ((padlen > 0) && (cnt < max)) {
445 0 : doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
446 0 : --padlen;
447 0 : ++cnt;
448 : }
449 0 : while (*value && (cnt < max)) {
450 0 : doapr_outch(sbuffer, buffer, currlen, maxlen, *value++);
451 0 : ++cnt;
452 : }
453 0 : while ((padlen < 0) && (cnt < max)) {
454 0 : doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
455 0 : ++padlen;
456 0 : ++cnt;
457 : }
458 0 : }
459 :
460 : static void
461 8880 : fmtint(char **sbuffer,
462 : char **buffer,
463 : size_t *currlen,
464 : size_t *maxlen, LLONG value, int base, int min, int max, int flags)
465 : {
466 : int signvalue = 0;
467 : const char *prefix = "";
468 : unsigned LLONG uvalue;
469 : char convert[DECIMAL_SIZE(value) + 3];
470 : int place = 0;
471 : int spadlen = 0;
472 : int zpadlen = 0;
473 : int caps = 0;
474 :
475 8880 : if (max < 0)
476 : max = 0;
477 8880 : uvalue = value;
478 8880 : if (!(flags & DP_F_UNSIGNED)) {
479 8880 : if (value < 0) {
480 : signvalue = '-';
481 0 : uvalue = -value;
482 8880 : } else if (flags & DP_F_PLUS)
483 : signvalue = '+';
484 8880 : else if (flags & DP_F_SPACE)
485 : signvalue = ' ';
486 : }
487 8880 : if (flags & DP_F_NUM) {
488 0 : if (base == 8)
489 : prefix = "0";
490 0 : if (base == 16)
491 : prefix = "0x";
492 : }
493 8880 : if (flags & DP_F_UP)
494 : caps = 1;
495 : do {
496 31920 : convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
497 15960 : [uvalue % (unsigned)base];
498 15960 : uvalue = (uvalue / (unsigned)base);
499 15960 : } while (uvalue && (place < (int)sizeof(convert)));
500 8880 : if (place == sizeof(convert))
501 : place--;
502 8880 : convert[place] = 0;
503 :
504 8880 : zpadlen = max - place;
505 17760 : spadlen =
506 17760 : min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix);
507 8880 : if (zpadlen < 0)
508 : zpadlen = 0;
509 8880 : if (spadlen < 0)
510 : spadlen = 0;
511 8880 : if (flags & DP_F_ZERO) {
512 8880 : zpadlen = OSSL_MAX(zpadlen, spadlen);
513 : spadlen = 0;
514 : }
515 8880 : if (flags & DP_F_MINUS)
516 0 : spadlen = -spadlen;
517 :
518 : /* spaces */
519 8880 : while (spadlen > 0) {
520 0 : doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
521 0 : --spadlen;
522 : }
523 :
524 : /* sign */
525 8880 : if (signvalue)
526 0 : doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
527 :
528 : /* prefix */
529 8880 : while (*prefix) {
530 0 : doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix);
531 0 : prefix++;
532 : }
533 :
534 : /* zeros */
535 8880 : if (zpadlen > 0) {
536 3600 : while (zpadlen > 0) {
537 1800 : doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
538 1800 : --zpadlen;
539 : }
540 : }
541 : /* digits */
542 24840 : while (place > 0)
543 15960 : doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]);
544 :
545 : /* left justified spaces */
546 8880 : while (spadlen < 0) {
547 0 : doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
548 0 : ++spadlen;
549 : }
550 8880 : return;
551 : }
552 :
553 : static LDOUBLE abs_val(LDOUBLE value)
554 : {
555 : LDOUBLE result = value;
556 0 : if (value < 0)
557 0 : result = -value;
558 : return result;
559 : }
560 :
561 : static LDOUBLE pow_10(int in_exp)
562 : {
563 : LDOUBLE result = 1;
564 0 : while (in_exp) {
565 0 : result *= 10;
566 0 : in_exp--;
567 : }
568 : return result;
569 : }
570 :
571 : static long roundv(LDOUBLE value)
572 : {
573 : long intpart;
574 0 : intpart = (long)value;
575 0 : value = value - intpart;
576 0 : if (value >= 0.5)
577 0 : intpart++;
578 : return intpart;
579 : }
580 :
581 : static void
582 0 : fmtfp(char **sbuffer,
583 : char **buffer,
584 : size_t *currlen,
585 : size_t *maxlen, LDOUBLE fvalue, int min, int max, int flags)
586 : {
587 : int signvalue = 0;
588 : LDOUBLE ufvalue;
589 : char iconvert[20];
590 : char fconvert[20];
591 : int iplace = 0;
592 : int fplace = 0;
593 : int padlen = 0;
594 : int zpadlen = 0;
595 : long intpart;
596 : long fracpart;
597 : long max10;
598 :
599 0 : if (max < 0)
600 : max = 6;
601 : ufvalue = abs_val(fvalue);
602 0 : if (fvalue < 0)
603 : signvalue = '-';
604 0 : else if (flags & DP_F_PLUS)
605 : signvalue = '+';
606 0 : else if (flags & DP_F_SPACE)
607 : signvalue = ' ';
608 :
609 0 : intpart = (long)ufvalue;
610 :
611 : /*
612 : * sorry, we only support 9 digits past the decimal because of our
613 : * conversion method
614 : */
615 0 : if (max > 9)
616 : max = 9;
617 :
618 : /*
619 : * we "cheat" by converting the fractional part to integer by multiplying
620 : * by a factor of 10
621 : */
622 : max10 = roundv(pow_10(max));
623 0 : fracpart = roundv(pow_10(max) * (ufvalue - intpart));
624 :
625 0 : if (fracpart >= max10) {
626 0 : intpart++;
627 0 : fracpart -= max10;
628 : }
629 :
630 : /* convert integer part */
631 : do {
632 0 : iconvert[iplace++] = "0123456789"[intpart % 10];
633 0 : intpart = (intpart / 10);
634 0 : } while (intpart && (iplace < (int)sizeof(iconvert)));
635 0 : if (iplace == sizeof iconvert)
636 : iplace--;
637 0 : iconvert[iplace] = 0;
638 :
639 : /* convert fractional part */
640 : do {
641 0 : fconvert[fplace++] = "0123456789"[fracpart % 10];
642 0 : fracpart = (fracpart / 10);
643 0 : } while (fplace < max);
644 0 : if (fplace == sizeof fconvert)
645 : fplace--;
646 0 : fconvert[fplace] = 0;
647 :
648 : /* -1 for decimal point, another -1 if we are printing a sign */
649 0 : padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
650 0 : zpadlen = max - fplace;
651 0 : if (zpadlen < 0)
652 : zpadlen = 0;
653 0 : if (padlen < 0)
654 : padlen = 0;
655 0 : if (flags & DP_F_MINUS)
656 0 : padlen = -padlen;
657 :
658 0 : if ((flags & DP_F_ZERO) && (padlen > 0)) {
659 0 : if (signvalue) {
660 0 : doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
661 0 : --padlen;
662 : signvalue = 0;
663 : }
664 0 : while (padlen > 0) {
665 0 : doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
666 0 : --padlen;
667 : }
668 : }
669 0 : while (padlen > 0) {
670 0 : doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
671 0 : --padlen;
672 : }
673 0 : if (signvalue)
674 0 : doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
675 :
676 0 : while (iplace > 0)
677 0 : doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]);
678 :
679 : /*
680 : * Decimal point. This should probably use locale to find the correct
681 : * char to print out.
682 : */
683 0 : if (max > 0 || (flags & DP_F_NUM)) {
684 0 : doapr_outch(sbuffer, buffer, currlen, maxlen, '.');
685 :
686 0 : while (fplace > 0)
687 0 : doapr_outch(sbuffer, buffer, currlen, maxlen, fconvert[--fplace]);
688 : }
689 0 : while (zpadlen > 0) {
690 0 : doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
691 0 : --zpadlen;
692 : }
693 :
694 0 : while (padlen < 0) {
695 0 : doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
696 0 : ++padlen;
697 : }
698 0 : }
699 :
700 : static void
701 20720 : doapr_outch(char **sbuffer,
702 : char **buffer, size_t *currlen, size_t *maxlen, int c)
703 : {
704 : /* If we haven't at least one buffer, someone has doe a big booboo */
705 : assert(*sbuffer != NULL || buffer != NULL);
706 :
707 : /* |currlen| must always be <= |*maxlen| */
708 : assert(*currlen <= *maxlen);
709 :
710 20720 : if (buffer && *currlen == *maxlen) {
711 0 : *maxlen += 1024;
712 0 : if (*buffer == NULL) {
713 0 : *buffer = OPENSSL_malloc(*maxlen);
714 0 : if (!*buffer) {
715 : /* Panic! Can't really do anything sensible. Just return */
716 : return;
717 : }
718 0 : if (*currlen > 0) {
719 : assert(*sbuffer != NULL);
720 0 : memcpy(*buffer, *sbuffer, *currlen);
721 : }
722 0 : *sbuffer = NULL;
723 : } else {
724 0 : *buffer = OPENSSL_realloc(*buffer, *maxlen);
725 0 : if (!*buffer) {
726 : /* Panic! Can't really do anything sensible. Just return */
727 : return;
728 : }
729 : }
730 : }
731 :
732 20720 : if (*currlen < *maxlen) {
733 20720 : if (*sbuffer)
734 20720 : (*sbuffer)[(*currlen)++] = (char)c;
735 : else
736 0 : (*buffer)[(*currlen)++] = (char)c;
737 : }
738 :
739 : return;
740 : }
741 :
742 : /***************************************************************************/
743 :
744 0 : int BIO_printf(BIO *bio, const char *format, ...)
745 : {
746 : va_list args;
747 : int ret;
748 :
749 0 : va_start(args, format);
750 :
751 0 : ret = BIO_vprintf(bio, format, args);
752 :
753 0 : va_end(args);
754 0 : return (ret);
755 : }
756 :
757 0 : int BIO_vprintf(BIO *bio, const char *format, va_list args)
758 : {
759 : int ret;
760 : size_t retlen;
761 : char hugebuf[1024 * 2]; /* Was previously 10k, which is unreasonable
762 : * in small-stack environments, like threads
763 : * or DOS programs. */
764 0 : char *hugebufp = hugebuf;
765 0 : size_t hugebufsize = sizeof(hugebuf);
766 0 : char *dynbuf = NULL;
767 : int ignored;
768 :
769 : dynbuf = NULL;
770 0 : CRYPTO_push_info("doapr()");
771 0 : _dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format, args);
772 0 : if (dynbuf) {
773 0 : ret = BIO_write(bio, dynbuf, (int)retlen);
774 0 : OPENSSL_free(dynbuf);
775 : } else {
776 0 : ret = BIO_write(bio, hugebuf, (int)retlen);
777 : }
778 0 : CRYPTO_pop_info();
779 0 : return (ret);
780 : }
781 :
782 : /*
783 : * As snprintf is not available everywhere, we provide our own
784 : * implementation. This function has nothing to do with BIOs, but it's
785 : * closely related to BIO_printf, and we need *some* name prefix ... (XXX the
786 : * function should be renamed, but to what?)
787 : */
788 1480 : int BIO_snprintf(char *buf, size_t n, const char *format, ...)
789 : {
790 : va_list args;
791 : int ret;
792 :
793 1480 : va_start(args, format);
794 :
795 1480 : ret = BIO_vsnprintf(buf, n, format, args);
796 :
797 1480 : va_end(args);
798 1480 : return (ret);
799 : }
800 :
801 1480 : int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
802 : {
803 : size_t retlen;
804 : int truncated;
805 :
806 1480 : _dopr(&buf, NULL, &n, &retlen, &truncated, format, args);
807 :
808 1480 : if (truncated)
809 : /*
810 : * In case of truncation, return -1 like traditional snprintf.
811 : * (Current drafts for ISO/IEC 9899 say snprintf should return the
812 : * number of characters that would have been written, had the buffer
813 : * been large enough.)
814 : */
815 : return -1;
816 : else
817 1480 : return (retlen <= INT_MAX) ? (int)retlen : -1;
818 : }
|