]>
git.ipfire.org Git - thirdparty/openssl.git/blob - test/testutil/format_output.c
2 * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the OpenSSL license (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
10 #include "../testutil.h"
16 #include "internal/nelem.h"
18 /* The size of memory buffers to display on failure */
19 #define MEM_BUFFER_SIZE (2000)
20 #define MAX_STRING_WIDTH (80)
21 #define BN_OUTPUT_SIZE (8)
23 /* Output a diff header */
24 static void test_diff_header(const char *left
, const char *right
)
26 test_printf_stderr("--- %s\n", left
);
27 test_printf_stderr("+++ %s\n", right
);
30 /* Formatted string output routines */
31 static void test_string_null_empty(const char *m
, char c
)
34 test_printf_stderr("% 4s %c NULL\n", "", c
);
36 test_printf_stderr("% 4u:%c ''\n", 0u, c
);
39 static void test_fail_string_common(const char *prefix
, const char *file
,
40 int line
, const char *type
,
41 const char *left
, const char *right
,
42 const char *op
, const char *m1
, size_t l1
,
43 const char *m2
, size_t l2
)
45 const size_t width
= (MAX_STRING_WIDTH
- subtest_level() - 12) / 16 * 16;
46 char b1
[MAX_STRING_WIDTH
+ 1], b2
[MAX_STRING_WIDTH
+ 1];
47 char bdiff
[MAX_STRING_WIDTH
+ 1];
49 unsigned int cnt
= 0, diff
;
51 test_fail_message_prefix(prefix
, file
, line
, type
, left
, right
, op
);
56 if (l1
== 0 && l2
== 0) {
57 if ((m1
== NULL
) == (m2
== NULL
)) {
58 test_string_null_empty(m1
, ' ');
60 test_diff_header(left
, right
);
61 test_string_null_empty(m1
, '-');
62 test_string_null_empty(m2
, '+');
67 if (l1
!= l2
|| strcmp(m1
, m2
) != 0)
68 test_diff_header(left
, right
);
70 while (l1
> 0 || l2
> 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
] : '.';
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
] : '.';
84 if (n1
> 0 && n2
> 0) {
85 const size_t j
= n1
< n2
? n1
: n2
;
96 if (n1
== n2
&& !diff
) {
97 test_printf_stderr("% 4u: '%s'\n", cnt
, n2
> n1
? b2
: b1
);
99 if (cnt
== 0 && (m1
== NULL
|| *m1
== '\0'))
100 test_string_null_empty(m1
, '-');
102 test_printf_stderr("% 4u:- '%s'\n", cnt
, b1
);
103 if (cnt
== 0 && (m2
== NULL
|| *m2
== '\0'))
104 test_string_null_empty(m2
, '+');
106 test_printf_stderr("% 4u:+ '%s'\n", cnt
, b2
);
108 test_printf_stderr("% 4s %s\n", "", bdiff
);
121 * Wrapper routines so that the underlying code can be shared.
122 * The first is the call from inside the test utilities when a conditional
123 * fails. The second is the user's call to dump a string.
125 void test_fail_string_message(const char *prefix
, const char *file
,
126 int line
, const char *type
,
127 const char *left
, const char *right
,
128 const char *op
, const char *m1
, size_t l1
,
129 const char *m2
, size_t l2
)
131 test_fail_string_common(prefix
, file
, line
, type
, left
, right
, op
,
133 test_printf_stderr("\n");
136 void test_output_string(const char *name
, const char *m
, size_t l
)
138 test_fail_string_common("string", NULL
, 0, NULL
, NULL
, NULL
, name
,
142 /* BIGNUM formatted output routines */
145 * A basic memory byte to hex digit converter with allowance for spacing
148 static void hex_convert_memory(const unsigned char *m
, size_t n
, char *b
,
153 for (i
= 0; i
< n
; i
++) {
154 const unsigned char c
= *m
++;
156 *b
++ = "0123456789abcdef"[c
>> 4];
157 *b
++ = "0123456789abcdef"[c
& 15];
158 if (i
% width
== width
- 1 && i
!= n
- 1)
165 * Constants to define the number of bytes to display per line and the number
166 * of characters these take.
168 static const int bn_bytes
= (MAX_STRING_WIDTH
- 9) / (BN_OUTPUT_SIZE
* 2 + 1)
170 static const int bn_chars
= (MAX_STRING_WIDTH
- 9) / (BN_OUTPUT_SIZE
* 2 + 1)
171 * (BN_OUTPUT_SIZE
* 2 + 1) - 1;
174 * Output the header line for the bignum
176 static void test_bignum_header_line(void)
178 test_printf_stderr(" %*s\n", bn_chars
+ 6, "bit position");
181 static const char *test_bignum_zero_null(const BIGNUM
*bn
)
184 return BN_is_negative(bn
) ? "-0" : "0";
189 * Print a bignum zero taking care to include the correct sign.
190 * This routine correctly deals with a NULL bignum pointer as input.
192 static void test_bignum_zero_print(const BIGNUM
*bn
, char sep
)
194 const char *v
= test_bignum_zero_null(bn
);
195 const char *suf
= bn
!= NULL
? ": 0" : "";
197 test_printf_stderr("%c%*s%s\n", sep
, bn_chars
, v
, suf
);
201 * Convert a section of memory from inside a bignum into a displayable
202 * string with appropriate visual aid spaces inserted.
204 static int convert_bn_memory(const unsigned char *in
, size_t bytes
,
205 char *out
, int *lz
, const BIGNUM
*bn
)
207 int n
= bytes
* 2, i
;
208 char *p
= out
, *q
= NULL
;
210 if (bn
!= NULL
&& !BN_is_zero(bn
)) {
211 hex_convert_memory(in
, bytes
, out
, BN_OUTPUT_SIZE
);
213 for (; *p
== '0' || *p
== ' '; p
++)
221 * in[bytes] is defined because we're converting a non-zero
222 * number and we've not seen a non-zero yet.
224 if ((in
[bytes
] & 0xf0) != 0 && BN_is_negative(bn
)) {
231 if (BN_is_negative(bn
)) {
233 * This is valid because we always convert more digits than
244 for (i
= 0; i
< n
; i
++) {
246 if (i
% (2 * BN_OUTPUT_SIZE
) == 2 * BN_OUTPUT_SIZE
- 1 && i
!= n
- 1)
253 q
= BN_is_negative(bn
) ? "-0" : "0";
254 strcpy(p
- strlen(q
), q
);
259 * Common code to display either one or two bignums, including the diff
260 * pointers for changes (only when there are two).
262 static void test_fail_bignum_common(const char *prefix
, const char *file
,
263 int line
, const char *type
,
264 const char *left
, const char *right
,
266 const BIGNUM
*bn1
, const BIGNUM
*bn2
)
268 const size_t bytes
= bn_bytes
;
269 char b1
[MAX_STRING_WIDTH
+ 1], b2
[MAX_STRING_WIDTH
+ 1];
270 char *p
, bdiff
[MAX_STRING_WIDTH
+ 1];
271 size_t l1
, l2
, n1
, n2
, i
, len
;
272 unsigned int cnt
, diff
, real_diff
;
273 unsigned char *m1
= NULL
, *m2
= NULL
;
274 int lz1
= 1, lz2
= 1;
275 unsigned char buffer
[MEM_BUFFER_SIZE
* 2], *bufp
= buffer
;
277 test_fail_message_prefix(prefix
, file
, line
, type
, left
, right
, op
);
278 l1
= bn1
== NULL
? 0 : (BN_num_bytes(bn1
) + (BN_is_negative(bn1
) ? 1 : 0));
279 l2
= bn2
== NULL
? 0 : (BN_num_bytes(bn2
) + (BN_is_negative(bn2
) ? 1 : 0));
280 if (l1
== 0 && l2
== 0) {
281 if ((bn1
== NULL
) == (bn2
== NULL
)) {
282 test_bignum_header_line();
283 test_bignum_zero_print(bn1
, ' ');
285 test_diff_header(left
, right
);
286 test_bignum_header_line();
287 test_bignum_zero_print(bn1
, '-');
288 test_bignum_zero_print(bn2
, '+');
293 if (l1
!= l2
|| bn1
== NULL
|| bn2
== NULL
|| BN_cmp(bn1
, bn2
) != 0)
294 test_diff_header(left
, right
);
295 test_bignum_header_line();
297 len
= ((l1
> l2
? l1
: l2
) + bytes
- 1) / bytes
* bytes
;
299 if (len
> MEM_BUFFER_SIZE
&& (bufp
= OPENSSL_malloc(len
* 2)) == NULL
) {
301 len
= MEM_BUFFER_SIZE
;
302 test_printf_stderr("WARNING: these BIGNUMs have been truncated\n");
307 BN_bn2binpad(bn1
, m1
, len
);
311 BN_bn2binpad(bn2
, m2
, len
);
315 cnt
= 8 * (len
- bytes
);
316 n1
= convert_bn_memory(m1
, bytes
, b1
, &lz1
, bn1
);
317 n2
= convert_bn_memory(m2
, bytes
, b2
, &lz2
, bn2
);
319 diff
= real_diff
= 0;
322 for (i
=0; b1
[i
] != '\0'; i
++)
323 if (b1
[i
] == b2
[i
] || b1
[i
] == ' ' || b2
[i
] == ' ') {
325 diff
|= b1
[i
] != b2
[i
];
328 real_diff
= diff
= 1;
332 test_printf_stderr(" %s:% 5d\n", n2
> n1
? b2
: b1
, cnt
);
334 if (cnt
== 0 && bn1
== NULL
)
335 test_printf_stderr("-%s\n", b1
);
336 else if (cnt
== 0 || n1
> 0)
337 test_printf_stderr("-%s:% 5d\n", b1
, cnt
);
338 if (cnt
== 0 && bn2
== NULL
)
339 test_printf_stderr("+%s\n", b2
);
340 else if (cnt
== 0 || n2
> 0)
341 test_printf_stderr("+%s:% 5d\n", b2
, cnt
);
342 if (real_diff
&& (cnt
== 0 || (n1
> 0 && n2
> 0))
343 && bn1
!= NULL
&& bn2
!= NULL
)
344 test_printf_stderr(" %s\n", bdiff
);
359 * Wrapper routines so that the underlying code can be shared.
360 * The first two are calls from inside the test utilities when a conditional
361 * fails. The third is the user's call to dump a bignum.
363 void test_fail_bignum_message(const char *prefix
, const char *file
,
364 int line
, const char *type
,
365 const char *left
, const char *right
,
367 const BIGNUM
*bn1
, const BIGNUM
*bn2
)
369 test_fail_bignum_common(prefix
, file
, line
, type
, left
, right
, op
, bn1
, bn2
);
370 test_printf_stderr("\n");
373 void test_fail_bignum_mono_message(const char *prefix
, const char *file
,
374 int line
, const char *type
,
375 const char *left
, const char *right
,
376 const char *op
, const BIGNUM
*bn
)
378 test_fail_bignum_common(prefix
, file
, line
, type
, left
, right
, op
, bn
, bn
);
379 test_printf_stderr("\n");
382 void test_output_bignum(const char *name
, const BIGNUM
*bn
)
384 if (bn
== NULL
|| BN_is_zero(bn
)) {
385 test_printf_stderr("bignum: '%s' = %s\n", name
,
386 test_bignum_zero_null(bn
));
387 } else if (BN_num_bytes(bn
) <= BN_OUTPUT_SIZE
) {
388 unsigned char buf
[BN_OUTPUT_SIZE
];
389 char out
[2 * sizeof(buf
) + 1];
391 int n
= BN_bn2bin(bn
, buf
);
393 hex_convert_memory(buf
, n
, p
, BN_OUTPUT_SIZE
);
394 while (*p
== '0' && *++p
!= '\0')
396 test_printf_stderr("bignum: '%s' = %s0x%s\n", name
,
397 BN_is_negative(bn
) ? "-" : "", p
);
399 test_fail_bignum_common("bignum", NULL
, 0, NULL
, NULL
, NULL
, name
,
404 /* Memory output routines */
407 * Handle zero length blocks of memory or NULL pointers to memory
409 static void test_memory_null_empty(const unsigned char *m
, char c
)
412 test_printf_stderr("% 4s %c%s\n", "", c
, "NULL");
414 test_printf_stderr("%04x %c%s\n", 0u, c
, "empty");
418 * Common code to display one or two blocks of memory.
420 static void test_fail_memory_common(const char *prefix
, const char *file
,
421 int line
, const char *type
,
422 const char *left
, const char *right
,
424 const unsigned char *m1
, size_t l1
,
425 const unsigned char *m2
, size_t l2
)
427 const size_t bytes
= (MAX_STRING_WIDTH
- 9) / 17 * 8;
428 char b1
[MAX_STRING_WIDTH
+ 1], b2
[MAX_STRING_WIDTH
+ 1];
429 char *p
, bdiff
[MAX_STRING_WIDTH
+ 1];
431 unsigned int cnt
= 0, diff
;
433 test_fail_message_prefix(prefix
, file
, line
, type
, left
, right
, op
);
438 if (l1
== 0 && l2
== 0) {
439 if ((m1
== NULL
) == (m2
== NULL
)) {
440 test_memory_null_empty(m1
, ' ');
442 test_diff_header(left
, right
);
443 test_memory_null_empty(m1
, '-');
444 test_memory_null_empty(m2
, '+');
449 if (l1
!= l2
|| (m1
!= m2
&& memcmp(m1
, m2
, l1
) != 0))
450 test_diff_header(left
, right
);
452 while (l1
> 0 || l2
> 0) {
455 n1
= l1
> bytes
? bytes
: l1
;
456 hex_convert_memory(m1
, n1
, b1
, 8);
459 n2
= l2
> bytes
? bytes
: l2
;
460 hex_convert_memory(m2
, n2
, b2
, 8);
466 if (n1
> 0 && n2
> 0) {
467 const size_t j
= n1
< n2
? n1
: n2
;
470 if (m1
[i
] == m2
[i
]) {
478 if (i
% 8 == 7 && i
!= j
- 1)
484 if (n1
== n2
&& !diff
) {
485 test_printf_stderr("%04x: %s\n", cnt
, b1
);
487 if (cnt
== 0 && (m1
== NULL
|| l1
== 0))
488 test_memory_null_empty(m1
, '-');
490 test_printf_stderr("%04x:-%s\n", cnt
, b1
);
491 if (cnt
== 0 && (m2
== NULL
|| l2
== 0))
492 test_memory_null_empty(m2
, '+');
494 test_printf_stderr("%04x:+%s\n", cnt
, b2
);
496 test_printf_stderr("% 4s %s\n", "", bdiff
);
509 * Wrapper routines so that the underlying code can be shared.
510 * The first is the call from inside the test utilities when a conditional
511 * fails. The second is the user's call to dump memory.
513 void test_fail_memory_message(const char *prefix
, const char *file
,
514 int line
, const char *type
,
515 const char *left
, const char *right
,
517 const unsigned char *m1
, size_t l1
,
518 const unsigned char *m2
, size_t l2
)
520 test_fail_memory_common(prefix
, file
, line
, type
, left
, right
, op
,
522 test_printf_stderr("\n");
525 void test_output_memory(const char *name
, const unsigned char *m
, size_t l
)
527 test_fail_memory_common("memory", NULL
, 0, NULL
, NULL
, NULL
, name
,