VirtualBox

source: vbox/trunk/src/libs/openssl-3.1.0/test/testutil/format_output.c@ 99507

最後變更 在這個檔案從99507是 99366,由 vboxsync 提交於 2 年 前

openssl-3.1.0: Applied and adjusted our OpenSSL changes to 3.0.7. bugref:10418

檔案大小: 16.8 KB
 
1/*
2 * Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10#include "../testutil.h"
11#include "output.h"
12#include "tu_local.h"
13
14#include <string.h>
15#include <ctype.h>
16
17/* The size of memory buffers to display on failure */
18#define MEM_BUFFER_SIZE (2000)
19#define MAX_STRING_WIDTH (80)
20#define BN_OUTPUT_SIZE (8)
21
22/* Output a diff header */
23static void test_diff_header(const char *left, const char *right)
24{
25 test_printf_stderr("--- %s\n", left);
26 test_printf_stderr("+++ %s\n", right);
27}
28
29/* Formatted string output routines */
30static void test_string_null_empty(const char *m, char c)
31{
32 if (m == NULL)
33 test_printf_stderr("%4s %c NULL\n", "", c);
34 else
35 test_printf_stderr("%4u:%c ''\n", 0u, c);
36}
37
38static void test_fail_string_common(const char *prefix, const char *file,
39 int line, const char *type,
40 const char *left, const char *right,
41 const char *op, const char *m1, size_t l1,
42 const char *m2, size_t l2)
43{
44 const size_t width =
45 (MAX_STRING_WIDTH - BIO_get_indent(bio_err) - 12) / 16 * 16;
46 char b1[MAX_STRING_WIDTH + 1], b2[MAX_STRING_WIDTH + 1];
47 char bdiff[MAX_STRING_WIDTH + 1];
48 size_t n1, n2, i;
49 unsigned int cnt = 0, diff;
50
51 test_fail_message_prefix(prefix, file, line, type, left, right, op);
52 if (m1 == NULL)
53 l1 = 0;
54 if (m2 == NULL)
55 l2 = 0;
56 if (l1 == 0 && l2 == 0) {
57 if ((m1 == NULL) == (m2 == NULL)) {
58 test_string_null_empty(m1, ' ');
59 } else {
60 test_diff_header(left, right);
61 test_string_null_empty(m1, '-');
62 test_string_null_empty(m2, '+');
63 }
64 goto fin;
65 }
66
67 if (l1 != l2 || strncmp(m1, m2, l1) != 0)
68 test_diff_header(left, right);
69
70 while (l1 > 0 || l2 > 0) {
71 n1 = n2 = 0;
72 if (l1 > 0) {
73 b1[n1 = l1 > width ? width : l1] = 0;
74 for (i = 0; i < n1; i++)
75 b1[i] = isprint((unsigned char)m1[i]) ? m1[i] : '.';
76 }
77 if (l2 > 0) {
78 b2[n2 = l2 > width ? width : l2] = 0;
79 for (i = 0; i < n2; i++)
80 b2[i] = isprint((unsigned char)m2[i]) ? m2[i] : '.';
81 }
82 diff = 0;
83 i = 0;
84 if (n1 > 0 && n2 > 0) {
85 const size_t j = n1 < n2 ? n1 : n2;
86
87 for (; i < j; i++)
88 if (m1[i] == m2[i]) {
89 bdiff[i] = ' ';
90 } else {
91 bdiff[i] = '^';
92 diff = 1;
93 }
94 bdiff[i] = '\0';
95 }
96 if (n1 == n2 && !diff) {
97 test_printf_stderr("%4u: '%s'\n", cnt, n2 > n1 ? b2 : b1);
98 } else {
99 if (cnt == 0 && (m1 == NULL || *m1 == '\0'))
100 test_string_null_empty(m1, '-');
101 else if (n1 > 0)
102 test_printf_stderr("%4u:- '%s'\n", cnt, b1);
103 if (cnt == 0 && (m2 == NULL || *m2 == '\0'))
104 test_string_null_empty(m2, '+');
105 else if (n2 > 0)
106 test_printf_stderr("%4u:+ '%s'\n", cnt, b2);
107 if (diff && i > 0)
108 test_printf_stderr("%4s %s\n", "", bdiff);
109 }
110 if (m1 != NULL)
111 m1 += n1;
112 if (m2 != NULL)
113 m2 += n2;
114 l1 -= n1;
115 l2 -= n2;
116 cnt += width;
117 }
118fin:
119 test_flush_stderr();
120}
121
122/*
123 * Wrapper routines so that the underlying code can be shared.
124 * The first is the call from inside the test utilities when a conditional
125 * fails. The second is the user's call to dump a string.
126 */
127void test_fail_string_message(const char *prefix, const char *file,
128 int line, const char *type,
129 const char *left, const char *right,
130 const char *op, const char *m1, size_t l1,
131 const char *m2, size_t l2)
132{
133 test_fail_string_common(prefix, file, line, type, left, right, op,
134 m1, l1, m2, l2);
135 test_printf_stderr("\n");
136}
137
138void test_output_string(const char *name, const char *m, size_t l)
139{
140 test_fail_string_common("string", NULL, 0, NULL, NULL, NULL, name,
141 m, l, m, l);
142}
143
144/* BIGNUM formatted output routines */
145
146/*
147 * A basic memory byte to hex digit converter with allowance for spacing
148 * every so often.
149 */
150static void hex_convert_memory(const unsigned char *m, size_t n, char *b,
151 size_t width)
152{
153 size_t i;
154
155 for (i = 0; i < n; i++) {
156 const unsigned char c = *m++;
157
158 *b++ = "0123456789abcdef"[c >> 4];
159 *b++ = "0123456789abcdef"[c & 15];
160 if (i % width == width - 1 && i != n - 1)
161 *b++ = ' ';
162 }
163 *b = '\0';
164}
165
166/*
167 * Constants to define the number of bytes to display per line and the number
168 * of characters these take.
169 */
170static const int bn_bytes = (MAX_STRING_WIDTH - 9) / (BN_OUTPUT_SIZE * 2 + 1)
171 * BN_OUTPUT_SIZE;
172static const int bn_chars = (MAX_STRING_WIDTH - 9) / (BN_OUTPUT_SIZE * 2 + 1)
173 * (BN_OUTPUT_SIZE * 2 + 1) - 1;
174
175/*
176 * Output the header line for the bignum
177 */
178static void test_bignum_header_line(void)
179{
180 test_printf_stderr(" %*s\n", bn_chars + 6, "bit position");
181}
182
183static const char *test_bignum_zero_null(const BIGNUM *bn)
184{
185 if (bn != NULL)
186 return BN_is_negative(bn) ? "-0" : "0";
187 return "NULL";
188}
189
190/*
191 * Print a bignum zero taking care to include the correct sign.
192 * This routine correctly deals with a NULL bignum pointer as input.
193 */
194static void test_bignum_zero_print(const BIGNUM *bn, char sep)
195{
196 const char *v = test_bignum_zero_null(bn);
197 const char *suf = bn != NULL ? ": 0" : "";
198
199 test_printf_stderr("%c%*s%s\n", sep, bn_chars, v, suf);
200}
201
202/*
203 * Convert a section of memory from inside a bignum into a displayable
204 * string with appropriate visual aid spaces inserted.
205 */
206static int convert_bn_memory(const unsigned char *in, size_t bytes,
207 char *out, int *lz, const BIGNUM *bn)
208{
209 int n = bytes * 2, i;
210 char *p = out, *q = NULL;
211 const char *r;
212
213 if (bn != NULL && !BN_is_zero(bn)) {
214 hex_convert_memory(in, bytes, out, BN_OUTPUT_SIZE);
215 if (*lz) {
216 for (; *p == '0' || *p == ' '; p++)
217 if (*p == '0') {
218 q = p;
219 *p = ' ';
220 n--;
221 }
222 if (*p == '\0') {
223 /*
224 * in[bytes] is defined because we're converting a non-zero
225 * number and we've not seen a non-zero yet.
226 */
227 if ((in[bytes] & 0xf0) != 0 && BN_is_negative(bn)) {
228 *lz = 0;
229 *q = '-';
230 n++;
231 }
232 } else {
233 *lz = 0;
234 if (BN_is_negative(bn)) {
235 /*
236 * This is valid because we always convert more digits than
237 * the number holds.
238 */
239 *q = '-';
240 n++;
241 }
242 }
243 }
244 return n;
245 }
246
247 for (i = 0; i < n; i++) {
248 *p++ = ' ';
249 if (i % (2 * BN_OUTPUT_SIZE) == 2 * BN_OUTPUT_SIZE - 1 && i != n - 1)
250 *p++ = ' ';
251 }
252 *p = '\0';
253 if (bn == NULL)
254 r = "NULL";
255 else
256 r = BN_is_negative(bn) ? "-0" : "0";
257 strcpy(p - strlen(r), r);
258 return 0;
259}
260
261/*
262 * Common code to display either one or two bignums, including the diff
263 * pointers for changes (only when there are two).
264 */
265static void test_fail_bignum_common(const char *prefix, const char *file,
266 int line, const char *type,
267 const char *left, const char *right,
268 const char *op,
269 const BIGNUM *bn1, const BIGNUM *bn2)
270{
271 const size_t bytes = bn_bytes;
272 char b1[MAX_STRING_WIDTH + 1], b2[MAX_STRING_WIDTH + 1];
273 char *p, bdiff[MAX_STRING_WIDTH + 1];
274 size_t l1, l2, n1, n2, i, len;
275 unsigned int cnt, diff, real_diff;
276 unsigned char *m1 = NULL, *m2 = NULL;
277 int lz1 = 1, lz2 = 1;
278 unsigned char buffer[MEM_BUFFER_SIZE * 2], *bufp = buffer;
279
280 test_fail_message_prefix(prefix, file, line, type, left, right, op);
281 l1 = bn1 == NULL ? 0 : (BN_num_bytes(bn1) + (BN_is_negative(bn1) ? 1 : 0));
282 l2 = bn2 == NULL ? 0 : (BN_num_bytes(bn2) + (BN_is_negative(bn2) ? 1 : 0));
283 if (l1 == 0 && l2 == 0) {
284 if ((bn1 == NULL) == (bn2 == NULL)) {
285 test_bignum_header_line();
286 test_bignum_zero_print(bn1, ' ');
287 } else {
288 test_diff_header(left, right);
289 test_bignum_header_line();
290 test_bignum_zero_print(bn1, '-');
291 test_bignum_zero_print(bn2, '+');
292 }
293 goto fin;
294 }
295
296 if (l1 != l2 || bn1 == NULL || bn2 == NULL || BN_cmp(bn1, bn2) != 0)
297 test_diff_header(left, right);
298 test_bignum_header_line();
299
300 len = ((l1 > l2 ? l1 : l2) + bytes - 1) / bytes * bytes;
301
302 if (len > MEM_BUFFER_SIZE && (bufp = OPENSSL_malloc(len * 2)) == NULL) {
303 bufp = buffer;
304 len = MEM_BUFFER_SIZE;
305 test_printf_stderr("WARNING: these BIGNUMs have been truncated\n");
306 }
307
308 if (bn1 != NULL) {
309 m1 = bufp;
310 BN_bn2binpad(bn1, m1, len);
311 }
312 if (bn2 != NULL) {
313 m2 = bufp + len;
314 BN_bn2binpad(bn2, m2, len);
315 }
316
317 while (len > 0) {
318 cnt = 8 * (len - bytes);
319 n1 = convert_bn_memory(m1, bytes, b1, &lz1, bn1);
320 n2 = convert_bn_memory(m2, bytes, b2, &lz2, bn2);
321
322 diff = real_diff = 0;
323 i = 0;
324 p = bdiff;
325 for (i=0; b1[i] != '\0'; i++)
326 if (b1[i] == b2[i] || b1[i] == ' ' || b2[i] == ' ') {
327 *p++ = ' ';
328 diff |= b1[i] != b2[i];
329 } else {
330 *p++ = '^';
331 real_diff = diff = 1;
332 }
333 *p++ = '\0';
334 if (!diff) {
335 test_printf_stderr(" %s:% 5d\n", n2 > n1 ? b2 : b1, cnt);
336 } else {
337 if (cnt == 0 && bn1 == NULL)
338 test_printf_stderr("-%s\n", b1);
339 else if (cnt == 0 || n1 > 0)
340 test_printf_stderr("-%s:% 5d\n", b1, cnt);
341 if (cnt == 0 && bn2 == NULL)
342 test_printf_stderr("+%s\n", b2);
343 else if (cnt == 0 || n2 > 0)
344 test_printf_stderr("+%s:% 5d\n", b2, cnt);
345 if (real_diff && (cnt == 0 || (n1 > 0 && n2 > 0))
346 && bn1 != NULL && bn2 != NULL)
347 test_printf_stderr(" %s\n", bdiff);
348 }
349 if (m1 != NULL)
350 m1 += bytes;
351 if (m2 != NULL)
352 m2 += bytes;
353 len -= bytes;
354 }
355fin:
356 test_flush_stderr();
357 if (bufp != buffer)
358 OPENSSL_free(bufp);
359}
360
361/*
362 * Wrapper routines so that the underlying code can be shared.
363 * The first two are calls from inside the test utilities when a conditional
364 * fails. The third is the user's call to dump a bignum.
365 */
366void test_fail_bignum_message(const char *prefix, const char *file,
367 int line, const char *type,
368 const char *left, const char *right,
369 const char *op,
370 const BIGNUM *bn1, const BIGNUM *bn2)
371{
372 test_fail_bignum_common(prefix, file, line, type, left, right, op, bn1, bn2);
373 test_printf_stderr("\n");
374}
375
376void test_fail_bignum_mono_message(const char *prefix, const char *file,
377 int line, const char *type,
378 const char *left, const char *right,
379 const char *op, const BIGNUM *bn)
380{
381 test_fail_bignum_common(prefix, file, line, type, left, right, op, bn, bn);
382 test_printf_stderr("\n");
383}
384
385void test_output_bignum(const char *name, const BIGNUM *bn)
386{
387 if (bn == NULL || BN_is_zero(bn)) {
388 test_printf_stderr("bignum: '%s' = %s\n", name,
389 test_bignum_zero_null(bn));
390 } else if (BN_num_bytes(bn) <= BN_OUTPUT_SIZE) {
391 unsigned char buf[BN_OUTPUT_SIZE];
392 char out[2 * sizeof(buf) + 1];
393 char *p = out;
394 int n = BN_bn2bin(bn, buf);
395
396 hex_convert_memory(buf, n, p, BN_OUTPUT_SIZE);
397 while (*p == '0' && *++p != '\0')
398 ;
399 test_printf_stderr("bignum: '%s' = %s0x%s\n", name,
400 BN_is_negative(bn) ? "-" : "", p);
401 } else {
402 test_fail_bignum_common("bignum", NULL, 0, NULL, NULL, NULL, name,
403 bn, bn);
404 }
405}
406
407/* Memory output routines */
408
409/*
410 * Handle zero length blocks of memory or NULL pointers to memory
411 */
412static void test_memory_null_empty(const unsigned char *m, char c)
413{
414 if (m == NULL)
415 test_printf_stderr("%4s %c%s\n", "", c, "NULL");
416 else
417 test_printf_stderr("%04x %c%s\n", 0u, c, "empty");
418}
419
420/*
421 * Common code to display one or two blocks of memory.
422 */
423static void test_fail_memory_common(const char *prefix, const char *file,
424 int line, const char *type,
425 const char *left, const char *right,
426 const char *op,
427 const unsigned char *m1, size_t l1,
428 const unsigned char *m2, size_t l2)
429{
430 const size_t bytes = (MAX_STRING_WIDTH - 9) / 17 * 8;
431 char b1[MAX_STRING_WIDTH + 1], b2[MAX_STRING_WIDTH + 1];
432 char *p, bdiff[MAX_STRING_WIDTH + 1];
433 size_t n1, n2, i;
434 unsigned int cnt = 0, diff;
435
436 test_fail_message_prefix(prefix, file, line, type, left, right, op);
437 if (m1 == NULL)
438 l1 = 0;
439 if (m2 == NULL)
440 l2 = 0;
441 if (l1 == 0 && l2 == 0) {
442 if ((m1 == NULL) == (m2 == NULL)) {
443 test_memory_null_empty(m1, ' ');
444 } else {
445 test_diff_header(left, right);
446 test_memory_null_empty(m1, '-');
447 test_memory_null_empty(m2, '+');
448 }
449 goto fin;
450 }
451
452 if (l1 != l2 || (m1 != m2 && memcmp(m1, m2, l1) != 0))
453 test_diff_header(left, right);
454
455 while (l1 > 0 || l2 > 0) {
456 n1 = n2 = 0;
457 if (l1 > 0) {
458 n1 = l1 > bytes ? bytes : l1;
459 hex_convert_memory(m1, n1, b1, 8);
460 }
461 if (l2 > 0) {
462 n2 = l2 > bytes ? bytes : l2;
463 hex_convert_memory(m2, n2, b2, 8);
464 }
465
466 diff = 0;
467 i = 0;
468 p = bdiff;
469 if (n1 > 0 && n2 > 0) {
470 const size_t j = n1 < n2 ? n1 : n2;
471
472 for (; i < j; i++) {
473 if (m1[i] == m2[i]) {
474 *p++ = ' ';
475 *p++ = ' ';
476 } else {
477 *p++ = '^';
478 *p++ = '^';
479 diff = 1;
480 }
481 if (i % 8 == 7 && i != j - 1)
482 *p++ = ' ';
483 }
484 *p++ = '\0';
485 }
486
487 if (n1 == n2 && !diff) {
488 test_printf_stderr("%04x: %s\n", cnt, b1);
489 } else {
490 if (cnt == 0 && (m1 == NULL || l1 == 0))
491 test_memory_null_empty(m1, '-');
492 else if (n1 > 0)
493 test_printf_stderr("%04x:-%s\n", cnt, b1);
494 if (cnt == 0 && (m2 == NULL || l2 == 0))
495 test_memory_null_empty(m2, '+');
496 else if (n2 > 0)
497 test_printf_stderr("%04x:+%s\n", cnt, b2);
498 if (diff && i > 0)
499 test_printf_stderr("%4s %s\n", "", bdiff);
500 }
501 if (m1 != NULL)
502 m1 += n1;
503 if (m2 != NULL)
504 m2 += n2;
505 l1 -= n1;
506 l2 -= n2;
507 cnt += bytes;
508 }
509fin:
510 test_flush_stderr();
511}
512
513/*
514 * Wrapper routines so that the underlying code can be shared.
515 * The first is the call from inside the test utilities when a conditional
516 * fails. The second is the user's call to dump memory.
517 */
518void test_fail_memory_message(const char *prefix, const char *file,
519 int line, const char *type,
520 const char *left, const char *right,
521 const char *op,
522 const unsigned char *m1, size_t l1,
523 const unsigned char *m2, size_t l2)
524{
525 test_fail_memory_common(prefix, file, line, type, left, right, op,
526 m1, l1, m2, l2);
527 test_printf_stderr("\n");
528}
529
530void test_output_memory(const char *name, const unsigned char *m, size_t l)
531{
532 test_fail_memory_common("memory", NULL, 0, NULL, NULL, NULL, name,
533 m, l, m, l);
534}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette