1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <stdio.h> 11e1051a39Sopenharmony_ci#include <string.h> 12e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 13e1051a39Sopenharmony_ci#include "crypto/ctype.h" 14e1051a39Sopenharmony_ci#include "internal/numbers.h" 15e1051a39Sopenharmony_ci#include <openssl/bio.h> 16e1051a39Sopenharmony_ci#include <openssl/configuration.h> 17e1051a39Sopenharmony_ci 18e1051a39Sopenharmony_ci/* 19e1051a39Sopenharmony_ci * Copyright Patrick Powell 1995 20e1051a39Sopenharmony_ci * This code is based on code written by Patrick Powell <papowell@astart.com> 21e1051a39Sopenharmony_ci * It may be used for any purpose as long as this notice remains intact 22e1051a39Sopenharmony_ci * on all source code distributions. 23e1051a39Sopenharmony_ci */ 24e1051a39Sopenharmony_ci 25e1051a39Sopenharmony_ci#ifdef HAVE_LONG_DOUBLE 26e1051a39Sopenharmony_ci# define LDOUBLE long double 27e1051a39Sopenharmony_ci#else 28e1051a39Sopenharmony_ci# define LDOUBLE double 29e1051a39Sopenharmony_ci#endif 30e1051a39Sopenharmony_ci 31e1051a39Sopenharmony_cistatic int fmtstr(char **, char **, size_t *, size_t *, 32e1051a39Sopenharmony_ci const char *, int, int, int); 33e1051a39Sopenharmony_cistatic int fmtint(char **, char **, size_t *, size_t *, 34e1051a39Sopenharmony_ci int64_t, int, int, int, int); 35e1051a39Sopenharmony_ci#ifndef OPENSSL_SYS_UEFI 36e1051a39Sopenharmony_cistatic int fmtfp(char **, char **, size_t *, size_t *, 37e1051a39Sopenharmony_ci LDOUBLE, int, int, int, int); 38e1051a39Sopenharmony_ci#endif 39e1051a39Sopenharmony_cistatic int doapr_outch(char **, char **, size_t *, size_t *, int); 40e1051a39Sopenharmony_cistatic int _dopr(char **sbuffer, char **buffer, 41e1051a39Sopenharmony_ci size_t *maxlen, size_t *retlen, int *truncated, 42e1051a39Sopenharmony_ci const char *format, va_list args); 43e1051a39Sopenharmony_ci 44e1051a39Sopenharmony_ci/* format read states */ 45e1051a39Sopenharmony_ci#define DP_S_DEFAULT 0 46e1051a39Sopenharmony_ci#define DP_S_FLAGS 1 47e1051a39Sopenharmony_ci#define DP_S_MIN 2 48e1051a39Sopenharmony_ci#define DP_S_DOT 3 49e1051a39Sopenharmony_ci#define DP_S_MAX 4 50e1051a39Sopenharmony_ci#define DP_S_MOD 5 51e1051a39Sopenharmony_ci#define DP_S_CONV 6 52e1051a39Sopenharmony_ci#define DP_S_DONE 7 53e1051a39Sopenharmony_ci 54e1051a39Sopenharmony_ci/* format flags - Bits */ 55e1051a39Sopenharmony_ci/* left-aligned padding */ 56e1051a39Sopenharmony_ci#define DP_F_MINUS (1 << 0) 57e1051a39Sopenharmony_ci/* print an explicit '+' for a value with positive sign */ 58e1051a39Sopenharmony_ci#define DP_F_PLUS (1 << 1) 59e1051a39Sopenharmony_ci/* print an explicit ' ' for a value with positive sign */ 60e1051a39Sopenharmony_ci#define DP_F_SPACE (1 << 2) 61e1051a39Sopenharmony_ci/* print 0/0x prefix for octal/hex and decimal point for floating point */ 62e1051a39Sopenharmony_ci#define DP_F_NUM (1 << 3) 63e1051a39Sopenharmony_ci/* print leading zeroes */ 64e1051a39Sopenharmony_ci#define DP_F_ZERO (1 << 4) 65e1051a39Sopenharmony_ci/* print HEX in UPPPERcase */ 66e1051a39Sopenharmony_ci#define DP_F_UP (1 << 5) 67e1051a39Sopenharmony_ci/* treat value as unsigned */ 68e1051a39Sopenharmony_ci#define DP_F_UNSIGNED (1 << 6) 69e1051a39Sopenharmony_ci 70e1051a39Sopenharmony_ci/* conversion flags */ 71e1051a39Sopenharmony_ci#define DP_C_SHORT 1 72e1051a39Sopenharmony_ci#define DP_C_LONG 2 73e1051a39Sopenharmony_ci#define DP_C_LDOUBLE 3 74e1051a39Sopenharmony_ci#define DP_C_LLONG 4 75e1051a39Sopenharmony_ci#define DP_C_SIZE 5 76e1051a39Sopenharmony_ci 77e1051a39Sopenharmony_ci/* Floating point formats */ 78e1051a39Sopenharmony_ci#define F_FORMAT 0 79e1051a39Sopenharmony_ci#define E_FORMAT 1 80e1051a39Sopenharmony_ci#define G_FORMAT 2 81e1051a39Sopenharmony_ci 82e1051a39Sopenharmony_ci/* some handy macros */ 83e1051a39Sopenharmony_ci#define char_to_int(p) (p - '0') 84e1051a39Sopenharmony_ci#define OSSL_MAX(p,q) ((p >= q) ? p : q) 85e1051a39Sopenharmony_ci 86e1051a39Sopenharmony_cistatic int 87e1051a39Sopenharmony_ci_dopr(char **sbuffer, 88e1051a39Sopenharmony_ci char **buffer, 89e1051a39Sopenharmony_ci size_t *maxlen, 90e1051a39Sopenharmony_ci size_t *retlen, int *truncated, const char *format, va_list args) 91e1051a39Sopenharmony_ci{ 92e1051a39Sopenharmony_ci char ch; 93e1051a39Sopenharmony_ci int64_t value; 94e1051a39Sopenharmony_ci#ifndef OPENSSL_SYS_UEFI 95e1051a39Sopenharmony_ci LDOUBLE fvalue; 96e1051a39Sopenharmony_ci#endif 97e1051a39Sopenharmony_ci char *strvalue; 98e1051a39Sopenharmony_ci int min; 99e1051a39Sopenharmony_ci int max; 100e1051a39Sopenharmony_ci int state; 101e1051a39Sopenharmony_ci int flags; 102e1051a39Sopenharmony_ci int cflags; 103e1051a39Sopenharmony_ci size_t currlen; 104e1051a39Sopenharmony_ci 105e1051a39Sopenharmony_ci state = DP_S_DEFAULT; 106e1051a39Sopenharmony_ci flags = currlen = cflags = min = 0; 107e1051a39Sopenharmony_ci max = -1; 108e1051a39Sopenharmony_ci ch = *format++; 109e1051a39Sopenharmony_ci 110e1051a39Sopenharmony_ci while (state != DP_S_DONE) { 111e1051a39Sopenharmony_ci if (ch == '\0' || (buffer == NULL && currlen >= *maxlen)) 112e1051a39Sopenharmony_ci state = DP_S_DONE; 113e1051a39Sopenharmony_ci 114e1051a39Sopenharmony_ci switch (state) { 115e1051a39Sopenharmony_ci case DP_S_DEFAULT: 116e1051a39Sopenharmony_ci if (ch == '%') 117e1051a39Sopenharmony_ci state = DP_S_FLAGS; 118e1051a39Sopenharmony_ci else 119e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) 120e1051a39Sopenharmony_ci return 0; 121e1051a39Sopenharmony_ci ch = *format++; 122e1051a39Sopenharmony_ci break; 123e1051a39Sopenharmony_ci case DP_S_FLAGS: 124e1051a39Sopenharmony_ci switch (ch) { 125e1051a39Sopenharmony_ci case '-': 126e1051a39Sopenharmony_ci flags |= DP_F_MINUS; 127e1051a39Sopenharmony_ci ch = *format++; 128e1051a39Sopenharmony_ci break; 129e1051a39Sopenharmony_ci case '+': 130e1051a39Sopenharmony_ci flags |= DP_F_PLUS; 131e1051a39Sopenharmony_ci ch = *format++; 132e1051a39Sopenharmony_ci break; 133e1051a39Sopenharmony_ci case ' ': 134e1051a39Sopenharmony_ci flags |= DP_F_SPACE; 135e1051a39Sopenharmony_ci ch = *format++; 136e1051a39Sopenharmony_ci break; 137e1051a39Sopenharmony_ci case '#': 138e1051a39Sopenharmony_ci flags |= DP_F_NUM; 139e1051a39Sopenharmony_ci ch = *format++; 140e1051a39Sopenharmony_ci break; 141e1051a39Sopenharmony_ci case '0': 142e1051a39Sopenharmony_ci flags |= DP_F_ZERO; 143e1051a39Sopenharmony_ci ch = *format++; 144e1051a39Sopenharmony_ci break; 145e1051a39Sopenharmony_ci default: 146e1051a39Sopenharmony_ci state = DP_S_MIN; 147e1051a39Sopenharmony_ci break; 148e1051a39Sopenharmony_ci } 149e1051a39Sopenharmony_ci break; 150e1051a39Sopenharmony_ci case DP_S_MIN: 151e1051a39Sopenharmony_ci if (ossl_isdigit(ch)) { 152e1051a39Sopenharmony_ci min = 10 * min + char_to_int(ch); 153e1051a39Sopenharmony_ci ch = *format++; 154e1051a39Sopenharmony_ci } else if (ch == '*') { 155e1051a39Sopenharmony_ci min = va_arg(args, int); 156e1051a39Sopenharmony_ci ch = *format++; 157e1051a39Sopenharmony_ci state = DP_S_DOT; 158e1051a39Sopenharmony_ci } else 159e1051a39Sopenharmony_ci state = DP_S_DOT; 160e1051a39Sopenharmony_ci break; 161e1051a39Sopenharmony_ci case DP_S_DOT: 162e1051a39Sopenharmony_ci if (ch == '.') { 163e1051a39Sopenharmony_ci state = DP_S_MAX; 164e1051a39Sopenharmony_ci ch = *format++; 165e1051a39Sopenharmony_ci } else 166e1051a39Sopenharmony_ci state = DP_S_MOD; 167e1051a39Sopenharmony_ci break; 168e1051a39Sopenharmony_ci case DP_S_MAX: 169e1051a39Sopenharmony_ci if (ossl_isdigit(ch)) { 170e1051a39Sopenharmony_ci if (max < 0) 171e1051a39Sopenharmony_ci max = 0; 172e1051a39Sopenharmony_ci max = 10 * max + char_to_int(ch); 173e1051a39Sopenharmony_ci ch = *format++; 174e1051a39Sopenharmony_ci } else if (ch == '*') { 175e1051a39Sopenharmony_ci max = va_arg(args, int); 176e1051a39Sopenharmony_ci ch = *format++; 177e1051a39Sopenharmony_ci state = DP_S_MOD; 178e1051a39Sopenharmony_ci } else 179e1051a39Sopenharmony_ci state = DP_S_MOD; 180e1051a39Sopenharmony_ci break; 181e1051a39Sopenharmony_ci case DP_S_MOD: 182e1051a39Sopenharmony_ci switch (ch) { 183e1051a39Sopenharmony_ci case 'h': 184e1051a39Sopenharmony_ci cflags = DP_C_SHORT; 185e1051a39Sopenharmony_ci ch = *format++; 186e1051a39Sopenharmony_ci break; 187e1051a39Sopenharmony_ci case 'l': 188e1051a39Sopenharmony_ci if (*format == 'l') { 189e1051a39Sopenharmony_ci cflags = DP_C_LLONG; 190e1051a39Sopenharmony_ci format++; 191e1051a39Sopenharmony_ci } else 192e1051a39Sopenharmony_ci cflags = DP_C_LONG; 193e1051a39Sopenharmony_ci ch = *format++; 194e1051a39Sopenharmony_ci break; 195e1051a39Sopenharmony_ci case 'q': 196e1051a39Sopenharmony_ci case 'j': 197e1051a39Sopenharmony_ci cflags = DP_C_LLONG; 198e1051a39Sopenharmony_ci ch = *format++; 199e1051a39Sopenharmony_ci break; 200e1051a39Sopenharmony_ci case 'L': 201e1051a39Sopenharmony_ci cflags = DP_C_LDOUBLE; 202e1051a39Sopenharmony_ci ch = *format++; 203e1051a39Sopenharmony_ci break; 204e1051a39Sopenharmony_ci case 'z': 205e1051a39Sopenharmony_ci cflags = DP_C_SIZE; 206e1051a39Sopenharmony_ci ch = *format++; 207e1051a39Sopenharmony_ci break; 208e1051a39Sopenharmony_ci default: 209e1051a39Sopenharmony_ci break; 210e1051a39Sopenharmony_ci } 211e1051a39Sopenharmony_ci state = DP_S_CONV; 212e1051a39Sopenharmony_ci break; 213e1051a39Sopenharmony_ci case DP_S_CONV: 214e1051a39Sopenharmony_ci switch (ch) { 215e1051a39Sopenharmony_ci case 'd': 216e1051a39Sopenharmony_ci case 'i': 217e1051a39Sopenharmony_ci switch (cflags) { 218e1051a39Sopenharmony_ci case DP_C_SHORT: 219e1051a39Sopenharmony_ci value = (short int)va_arg(args, int); 220e1051a39Sopenharmony_ci break; 221e1051a39Sopenharmony_ci case DP_C_LONG: 222e1051a39Sopenharmony_ci value = va_arg(args, long int); 223e1051a39Sopenharmony_ci break; 224e1051a39Sopenharmony_ci case DP_C_LLONG: 225e1051a39Sopenharmony_ci value = va_arg(args, int64_t); 226e1051a39Sopenharmony_ci break; 227e1051a39Sopenharmony_ci case DP_C_SIZE: 228e1051a39Sopenharmony_ci value = va_arg(args, ossl_ssize_t); 229e1051a39Sopenharmony_ci break; 230e1051a39Sopenharmony_ci default: 231e1051a39Sopenharmony_ci value = va_arg(args, int); 232e1051a39Sopenharmony_ci break; 233e1051a39Sopenharmony_ci } 234e1051a39Sopenharmony_ci if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min, 235e1051a39Sopenharmony_ci max, flags)) 236e1051a39Sopenharmony_ci return 0; 237e1051a39Sopenharmony_ci break; 238e1051a39Sopenharmony_ci case 'X': 239e1051a39Sopenharmony_ci flags |= DP_F_UP; 240e1051a39Sopenharmony_ci /* FALLTHROUGH */ 241e1051a39Sopenharmony_ci case 'x': 242e1051a39Sopenharmony_ci case 'o': 243e1051a39Sopenharmony_ci case 'u': 244e1051a39Sopenharmony_ci flags |= DP_F_UNSIGNED; 245e1051a39Sopenharmony_ci switch (cflags) { 246e1051a39Sopenharmony_ci case DP_C_SHORT: 247e1051a39Sopenharmony_ci value = (unsigned short int)va_arg(args, unsigned int); 248e1051a39Sopenharmony_ci break; 249e1051a39Sopenharmony_ci case DP_C_LONG: 250e1051a39Sopenharmony_ci value = va_arg(args, unsigned long int); 251e1051a39Sopenharmony_ci break; 252e1051a39Sopenharmony_ci case DP_C_LLONG: 253e1051a39Sopenharmony_ci value = va_arg(args, uint64_t); 254e1051a39Sopenharmony_ci break; 255e1051a39Sopenharmony_ci case DP_C_SIZE: 256e1051a39Sopenharmony_ci value = va_arg(args, size_t); 257e1051a39Sopenharmony_ci break; 258e1051a39Sopenharmony_ci default: 259e1051a39Sopenharmony_ci value = va_arg(args, unsigned int); 260e1051a39Sopenharmony_ci break; 261e1051a39Sopenharmony_ci } 262e1051a39Sopenharmony_ci if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 263e1051a39Sopenharmony_ci ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), 264e1051a39Sopenharmony_ci min, max, flags)) 265e1051a39Sopenharmony_ci return 0; 266e1051a39Sopenharmony_ci break; 267e1051a39Sopenharmony_ci#ifndef OPENSSL_SYS_UEFI 268e1051a39Sopenharmony_ci case 'f': 269e1051a39Sopenharmony_ci if (cflags == DP_C_LDOUBLE) 270e1051a39Sopenharmony_ci fvalue = va_arg(args, LDOUBLE); 271e1051a39Sopenharmony_ci else 272e1051a39Sopenharmony_ci fvalue = va_arg(args, double); 273e1051a39Sopenharmony_ci if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, 274e1051a39Sopenharmony_ci flags, F_FORMAT)) 275e1051a39Sopenharmony_ci return 0; 276e1051a39Sopenharmony_ci break; 277e1051a39Sopenharmony_ci case 'E': 278e1051a39Sopenharmony_ci flags |= DP_F_UP; 279e1051a39Sopenharmony_ci /* fall thru */ 280e1051a39Sopenharmony_ci case 'e': 281e1051a39Sopenharmony_ci if (cflags == DP_C_LDOUBLE) 282e1051a39Sopenharmony_ci fvalue = va_arg(args, LDOUBLE); 283e1051a39Sopenharmony_ci else 284e1051a39Sopenharmony_ci fvalue = va_arg(args, double); 285e1051a39Sopenharmony_ci if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, 286e1051a39Sopenharmony_ci flags, E_FORMAT)) 287e1051a39Sopenharmony_ci return 0; 288e1051a39Sopenharmony_ci break; 289e1051a39Sopenharmony_ci case 'G': 290e1051a39Sopenharmony_ci flags |= DP_F_UP; 291e1051a39Sopenharmony_ci /* fall thru */ 292e1051a39Sopenharmony_ci case 'g': 293e1051a39Sopenharmony_ci if (cflags == DP_C_LDOUBLE) 294e1051a39Sopenharmony_ci fvalue = va_arg(args, LDOUBLE); 295e1051a39Sopenharmony_ci else 296e1051a39Sopenharmony_ci fvalue = va_arg(args, double); 297e1051a39Sopenharmony_ci if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, 298e1051a39Sopenharmony_ci flags, G_FORMAT)) 299e1051a39Sopenharmony_ci return 0; 300e1051a39Sopenharmony_ci break; 301e1051a39Sopenharmony_ci#else 302e1051a39Sopenharmony_ci case 'f': 303e1051a39Sopenharmony_ci case 'E': 304e1051a39Sopenharmony_ci case 'e': 305e1051a39Sopenharmony_ci case 'G': 306e1051a39Sopenharmony_ci case 'g': 307e1051a39Sopenharmony_ci /* not implemented for UEFI */ 308e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, ERR_R_UNSUPPORTED); 309e1051a39Sopenharmony_ci return 0; 310e1051a39Sopenharmony_ci#endif 311e1051a39Sopenharmony_ci case 'c': 312e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, 313e1051a39Sopenharmony_ci va_arg(args, int))) 314e1051a39Sopenharmony_ci return 0; 315e1051a39Sopenharmony_ci break; 316e1051a39Sopenharmony_ci case 's': 317e1051a39Sopenharmony_ci strvalue = va_arg(args, char *); 318e1051a39Sopenharmony_ci if (max < 0) { 319e1051a39Sopenharmony_ci if (buffer) 320e1051a39Sopenharmony_ci max = INT_MAX; 321e1051a39Sopenharmony_ci else 322e1051a39Sopenharmony_ci max = *maxlen; 323e1051a39Sopenharmony_ci } 324e1051a39Sopenharmony_ci if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue, 325e1051a39Sopenharmony_ci flags, min, max)) 326e1051a39Sopenharmony_ci return 0; 327e1051a39Sopenharmony_ci break; 328e1051a39Sopenharmony_ci case 'p': 329e1051a39Sopenharmony_ci value = (size_t)va_arg(args, void *); 330e1051a39Sopenharmony_ci if (!fmtint(sbuffer, buffer, &currlen, maxlen, 331e1051a39Sopenharmony_ci value, 16, min, max, flags | DP_F_NUM)) 332e1051a39Sopenharmony_ci return 0; 333e1051a39Sopenharmony_ci break; 334e1051a39Sopenharmony_ci case 'n': 335e1051a39Sopenharmony_ci { 336e1051a39Sopenharmony_ci int *num; 337e1051a39Sopenharmony_ci num = va_arg(args, int *); 338e1051a39Sopenharmony_ci *num = currlen; 339e1051a39Sopenharmony_ci } 340e1051a39Sopenharmony_ci break; 341e1051a39Sopenharmony_ci case '%': 342e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) 343e1051a39Sopenharmony_ci return 0; 344e1051a39Sopenharmony_ci break; 345e1051a39Sopenharmony_ci case 'w': 346e1051a39Sopenharmony_ci /* not supported yet, treat as next char */ 347e1051a39Sopenharmony_ci format++; 348e1051a39Sopenharmony_ci break; 349e1051a39Sopenharmony_ci default: 350e1051a39Sopenharmony_ci /* unknown, skip */ 351e1051a39Sopenharmony_ci break; 352e1051a39Sopenharmony_ci } 353e1051a39Sopenharmony_ci ch = *format++; 354e1051a39Sopenharmony_ci state = DP_S_DEFAULT; 355e1051a39Sopenharmony_ci flags = cflags = min = 0; 356e1051a39Sopenharmony_ci max = -1; 357e1051a39Sopenharmony_ci break; 358e1051a39Sopenharmony_ci case DP_S_DONE: 359e1051a39Sopenharmony_ci break; 360e1051a39Sopenharmony_ci default: 361e1051a39Sopenharmony_ci break; 362e1051a39Sopenharmony_ci } 363e1051a39Sopenharmony_ci } 364e1051a39Sopenharmony_ci /* 365e1051a39Sopenharmony_ci * We have to truncate if there is no dynamic buffer and we have filled the 366e1051a39Sopenharmony_ci * static buffer. 367e1051a39Sopenharmony_ci */ 368e1051a39Sopenharmony_ci if (buffer == NULL) { 369e1051a39Sopenharmony_ci *truncated = (currlen > *maxlen - 1); 370e1051a39Sopenharmony_ci if (*truncated) 371e1051a39Sopenharmony_ci currlen = *maxlen - 1; 372e1051a39Sopenharmony_ci } 373e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0')) 374e1051a39Sopenharmony_ci return 0; 375e1051a39Sopenharmony_ci *retlen = currlen - 1; 376e1051a39Sopenharmony_ci return 1; 377e1051a39Sopenharmony_ci} 378e1051a39Sopenharmony_ci 379e1051a39Sopenharmony_cistatic int 380e1051a39Sopenharmony_cifmtstr(char **sbuffer, 381e1051a39Sopenharmony_ci char **buffer, 382e1051a39Sopenharmony_ci size_t *currlen, 383e1051a39Sopenharmony_ci size_t *maxlen, const char *value, int flags, int min, int max) 384e1051a39Sopenharmony_ci{ 385e1051a39Sopenharmony_ci int padlen; 386e1051a39Sopenharmony_ci size_t strln; 387e1051a39Sopenharmony_ci int cnt = 0; 388e1051a39Sopenharmony_ci 389e1051a39Sopenharmony_ci if (value == 0) 390e1051a39Sopenharmony_ci value = "<NULL>"; 391e1051a39Sopenharmony_ci 392e1051a39Sopenharmony_ci strln = OPENSSL_strnlen(value, max < 0 ? SIZE_MAX : (size_t)max); 393e1051a39Sopenharmony_ci 394e1051a39Sopenharmony_ci padlen = min - strln; 395e1051a39Sopenharmony_ci if (min < 0 || padlen < 0) 396e1051a39Sopenharmony_ci padlen = 0; 397e1051a39Sopenharmony_ci if (max >= 0) { 398e1051a39Sopenharmony_ci /* 399e1051a39Sopenharmony_ci * Calculate the maximum output including padding. 400e1051a39Sopenharmony_ci * Make sure max doesn't overflow into negativity 401e1051a39Sopenharmony_ci */ 402e1051a39Sopenharmony_ci if (max < INT_MAX - padlen) 403e1051a39Sopenharmony_ci max += padlen; 404e1051a39Sopenharmony_ci else 405e1051a39Sopenharmony_ci max = INT_MAX; 406e1051a39Sopenharmony_ci } 407e1051a39Sopenharmony_ci if (flags & DP_F_MINUS) 408e1051a39Sopenharmony_ci padlen = -padlen; 409e1051a39Sopenharmony_ci 410e1051a39Sopenharmony_ci while ((padlen > 0) && (max < 0 || cnt < max)) { 411e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 412e1051a39Sopenharmony_ci return 0; 413e1051a39Sopenharmony_ci --padlen; 414e1051a39Sopenharmony_ci ++cnt; 415e1051a39Sopenharmony_ci } 416e1051a39Sopenharmony_ci while (strln > 0 && (max < 0 || cnt < max)) { 417e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++)) 418e1051a39Sopenharmony_ci return 0; 419e1051a39Sopenharmony_ci --strln; 420e1051a39Sopenharmony_ci ++cnt; 421e1051a39Sopenharmony_ci } 422e1051a39Sopenharmony_ci while ((padlen < 0) && (max < 0 || cnt < max)) { 423e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 424e1051a39Sopenharmony_ci return 0; 425e1051a39Sopenharmony_ci ++padlen; 426e1051a39Sopenharmony_ci ++cnt; 427e1051a39Sopenharmony_ci } 428e1051a39Sopenharmony_ci return 1; 429e1051a39Sopenharmony_ci} 430e1051a39Sopenharmony_ci 431e1051a39Sopenharmony_cistatic int 432e1051a39Sopenharmony_cifmtint(char **sbuffer, 433e1051a39Sopenharmony_ci char **buffer, 434e1051a39Sopenharmony_ci size_t *currlen, 435e1051a39Sopenharmony_ci size_t *maxlen, int64_t value, int base, int min, int max, int flags) 436e1051a39Sopenharmony_ci{ 437e1051a39Sopenharmony_ci int signvalue = 0; 438e1051a39Sopenharmony_ci const char *prefix = ""; 439e1051a39Sopenharmony_ci uint64_t uvalue; 440e1051a39Sopenharmony_ci char convert[DECIMAL_SIZE(value) + 3]; 441e1051a39Sopenharmony_ci int place = 0; 442e1051a39Sopenharmony_ci int spadlen = 0; 443e1051a39Sopenharmony_ci int zpadlen = 0; 444e1051a39Sopenharmony_ci int caps = 0; 445e1051a39Sopenharmony_ci 446e1051a39Sopenharmony_ci if (max < 0) 447e1051a39Sopenharmony_ci max = 0; 448e1051a39Sopenharmony_ci uvalue = value; 449e1051a39Sopenharmony_ci if (!(flags & DP_F_UNSIGNED)) { 450e1051a39Sopenharmony_ci if (value < 0) { 451e1051a39Sopenharmony_ci signvalue = '-'; 452e1051a39Sopenharmony_ci uvalue = 0 - (uint64_t)value; 453e1051a39Sopenharmony_ci } else if (flags & DP_F_PLUS) 454e1051a39Sopenharmony_ci signvalue = '+'; 455e1051a39Sopenharmony_ci else if (flags & DP_F_SPACE) 456e1051a39Sopenharmony_ci signvalue = ' '; 457e1051a39Sopenharmony_ci } 458e1051a39Sopenharmony_ci if (flags & DP_F_NUM) { 459e1051a39Sopenharmony_ci if (base == 8) 460e1051a39Sopenharmony_ci prefix = "0"; 461e1051a39Sopenharmony_ci if (base == 16) 462e1051a39Sopenharmony_ci prefix = "0x"; 463e1051a39Sopenharmony_ci } 464e1051a39Sopenharmony_ci if (flags & DP_F_UP) 465e1051a39Sopenharmony_ci caps = 1; 466e1051a39Sopenharmony_ci do { 467e1051a39Sopenharmony_ci convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef") 468e1051a39Sopenharmony_ci [uvalue % (unsigned)base]; 469e1051a39Sopenharmony_ci uvalue = (uvalue / (unsigned)base); 470e1051a39Sopenharmony_ci } while (uvalue && (place < (int)sizeof(convert))); 471e1051a39Sopenharmony_ci if (place == sizeof(convert)) 472e1051a39Sopenharmony_ci place--; 473e1051a39Sopenharmony_ci convert[place] = 0; 474e1051a39Sopenharmony_ci 475e1051a39Sopenharmony_ci zpadlen = max - place; 476e1051a39Sopenharmony_ci spadlen = 477e1051a39Sopenharmony_ci min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix); 478e1051a39Sopenharmony_ci if (zpadlen < 0) 479e1051a39Sopenharmony_ci zpadlen = 0; 480e1051a39Sopenharmony_ci if (spadlen < 0) 481e1051a39Sopenharmony_ci spadlen = 0; 482e1051a39Sopenharmony_ci if (flags & DP_F_ZERO) { 483e1051a39Sopenharmony_ci zpadlen = OSSL_MAX(zpadlen, spadlen); 484e1051a39Sopenharmony_ci spadlen = 0; 485e1051a39Sopenharmony_ci } 486e1051a39Sopenharmony_ci if (flags & DP_F_MINUS) 487e1051a39Sopenharmony_ci spadlen = -spadlen; 488e1051a39Sopenharmony_ci 489e1051a39Sopenharmony_ci /* spaces */ 490e1051a39Sopenharmony_ci while (spadlen > 0) { 491e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 492e1051a39Sopenharmony_ci return 0; 493e1051a39Sopenharmony_ci --spadlen; 494e1051a39Sopenharmony_ci } 495e1051a39Sopenharmony_ci 496e1051a39Sopenharmony_ci /* sign */ 497e1051a39Sopenharmony_ci if (signvalue) 498e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) 499e1051a39Sopenharmony_ci return 0; 500e1051a39Sopenharmony_ci 501e1051a39Sopenharmony_ci /* prefix */ 502e1051a39Sopenharmony_ci while (*prefix) { 503e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix)) 504e1051a39Sopenharmony_ci return 0; 505e1051a39Sopenharmony_ci prefix++; 506e1051a39Sopenharmony_ci } 507e1051a39Sopenharmony_ci 508e1051a39Sopenharmony_ci /* zeros */ 509e1051a39Sopenharmony_ci if (zpadlen > 0) { 510e1051a39Sopenharmony_ci while (zpadlen > 0) { 511e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) 512e1051a39Sopenharmony_ci return 0; 513e1051a39Sopenharmony_ci --zpadlen; 514e1051a39Sopenharmony_ci } 515e1051a39Sopenharmony_ci } 516e1051a39Sopenharmony_ci /* digits */ 517e1051a39Sopenharmony_ci while (place > 0) { 518e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place])) 519e1051a39Sopenharmony_ci return 0; 520e1051a39Sopenharmony_ci } 521e1051a39Sopenharmony_ci 522e1051a39Sopenharmony_ci /* left justified spaces */ 523e1051a39Sopenharmony_ci while (spadlen < 0) { 524e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 525e1051a39Sopenharmony_ci return 0; 526e1051a39Sopenharmony_ci ++spadlen; 527e1051a39Sopenharmony_ci } 528e1051a39Sopenharmony_ci return 1; 529e1051a39Sopenharmony_ci} 530e1051a39Sopenharmony_ci 531e1051a39Sopenharmony_ci#ifndef OPENSSL_SYS_UEFI 532e1051a39Sopenharmony_ci 533e1051a39Sopenharmony_cistatic LDOUBLE abs_val(LDOUBLE value) 534e1051a39Sopenharmony_ci{ 535e1051a39Sopenharmony_ci LDOUBLE result = value; 536e1051a39Sopenharmony_ci if (value < 0) 537e1051a39Sopenharmony_ci result = -value; 538e1051a39Sopenharmony_ci return result; 539e1051a39Sopenharmony_ci} 540e1051a39Sopenharmony_ci 541e1051a39Sopenharmony_cistatic LDOUBLE pow_10(int in_exp) 542e1051a39Sopenharmony_ci{ 543e1051a39Sopenharmony_ci LDOUBLE result = 1; 544e1051a39Sopenharmony_ci while (in_exp) { 545e1051a39Sopenharmony_ci result *= 10; 546e1051a39Sopenharmony_ci in_exp--; 547e1051a39Sopenharmony_ci } 548e1051a39Sopenharmony_ci return result; 549e1051a39Sopenharmony_ci} 550e1051a39Sopenharmony_ci 551e1051a39Sopenharmony_cistatic long roundv(LDOUBLE value) 552e1051a39Sopenharmony_ci{ 553e1051a39Sopenharmony_ci long intpart; 554e1051a39Sopenharmony_ci intpart = (long)value; 555e1051a39Sopenharmony_ci value = value - intpart; 556e1051a39Sopenharmony_ci if (value >= 0.5) 557e1051a39Sopenharmony_ci intpart++; 558e1051a39Sopenharmony_ci return intpart; 559e1051a39Sopenharmony_ci} 560e1051a39Sopenharmony_ci 561e1051a39Sopenharmony_cistatic int 562e1051a39Sopenharmony_cifmtfp(char **sbuffer, 563e1051a39Sopenharmony_ci char **buffer, 564e1051a39Sopenharmony_ci size_t *currlen, 565e1051a39Sopenharmony_ci size_t *maxlen, LDOUBLE fvalue, int min, int max, int flags, int style) 566e1051a39Sopenharmony_ci{ 567e1051a39Sopenharmony_ci int signvalue = 0; 568e1051a39Sopenharmony_ci LDOUBLE ufvalue; 569e1051a39Sopenharmony_ci LDOUBLE tmpvalue; 570e1051a39Sopenharmony_ci char iconvert[20]; 571e1051a39Sopenharmony_ci char fconvert[20]; 572e1051a39Sopenharmony_ci char econvert[20]; 573e1051a39Sopenharmony_ci int iplace = 0; 574e1051a39Sopenharmony_ci int fplace = 0; 575e1051a39Sopenharmony_ci int eplace = 0; 576e1051a39Sopenharmony_ci int padlen = 0; 577e1051a39Sopenharmony_ci int zpadlen = 0; 578e1051a39Sopenharmony_ci long exp = 0; 579e1051a39Sopenharmony_ci unsigned long intpart; 580e1051a39Sopenharmony_ci unsigned long fracpart; 581e1051a39Sopenharmony_ci unsigned long max10; 582e1051a39Sopenharmony_ci int realstyle; 583e1051a39Sopenharmony_ci 584e1051a39Sopenharmony_ci if (max < 0) 585e1051a39Sopenharmony_ci max = 6; 586e1051a39Sopenharmony_ci 587e1051a39Sopenharmony_ci if (fvalue < 0) 588e1051a39Sopenharmony_ci signvalue = '-'; 589e1051a39Sopenharmony_ci else if (flags & DP_F_PLUS) 590e1051a39Sopenharmony_ci signvalue = '+'; 591e1051a39Sopenharmony_ci else if (flags & DP_F_SPACE) 592e1051a39Sopenharmony_ci signvalue = ' '; 593e1051a39Sopenharmony_ci 594e1051a39Sopenharmony_ci /* 595e1051a39Sopenharmony_ci * G_FORMAT sometimes prints like E_FORMAT and sometimes like F_FORMAT 596e1051a39Sopenharmony_ci * depending on the number to be printed. Work out which one it is and use 597e1051a39Sopenharmony_ci * that from here on. 598e1051a39Sopenharmony_ci */ 599e1051a39Sopenharmony_ci if (style == G_FORMAT) { 600e1051a39Sopenharmony_ci if (fvalue == 0.0) { 601e1051a39Sopenharmony_ci realstyle = F_FORMAT; 602e1051a39Sopenharmony_ci } else if (fvalue < 0.0001) { 603e1051a39Sopenharmony_ci realstyle = E_FORMAT; 604e1051a39Sopenharmony_ci } else if ((max == 0 && fvalue >= 10) 605e1051a39Sopenharmony_ci || (max > 0 && fvalue >= pow_10(max))) { 606e1051a39Sopenharmony_ci realstyle = E_FORMAT; 607e1051a39Sopenharmony_ci } else { 608e1051a39Sopenharmony_ci realstyle = F_FORMAT; 609e1051a39Sopenharmony_ci } 610e1051a39Sopenharmony_ci } else { 611e1051a39Sopenharmony_ci realstyle = style; 612e1051a39Sopenharmony_ci } 613e1051a39Sopenharmony_ci 614e1051a39Sopenharmony_ci if (style != F_FORMAT) { 615e1051a39Sopenharmony_ci tmpvalue = fvalue; 616e1051a39Sopenharmony_ci /* Calculate the exponent */ 617e1051a39Sopenharmony_ci if (fvalue != 0.0) { 618e1051a39Sopenharmony_ci while (tmpvalue < 1) { 619e1051a39Sopenharmony_ci tmpvalue *= 10; 620e1051a39Sopenharmony_ci exp--; 621e1051a39Sopenharmony_ci } 622e1051a39Sopenharmony_ci while (tmpvalue > 10) { 623e1051a39Sopenharmony_ci tmpvalue /= 10; 624e1051a39Sopenharmony_ci exp++; 625e1051a39Sopenharmony_ci } 626e1051a39Sopenharmony_ci } 627e1051a39Sopenharmony_ci if (style == G_FORMAT) { 628e1051a39Sopenharmony_ci /* 629e1051a39Sopenharmony_ci * In G_FORMAT the "precision" represents significant digits. We 630e1051a39Sopenharmony_ci * always have at least 1 significant digit. 631e1051a39Sopenharmony_ci */ 632e1051a39Sopenharmony_ci if (max == 0) 633e1051a39Sopenharmony_ci max = 1; 634e1051a39Sopenharmony_ci /* Now convert significant digits to decimal places */ 635e1051a39Sopenharmony_ci if (realstyle == F_FORMAT) { 636e1051a39Sopenharmony_ci max -= (exp + 1); 637e1051a39Sopenharmony_ci if (max < 0) { 638e1051a39Sopenharmony_ci /* 639e1051a39Sopenharmony_ci * Should not happen. If we're in F_FORMAT then exp < max? 640e1051a39Sopenharmony_ci */ 641e1051a39Sopenharmony_ci (void)doapr_outch(sbuffer, buffer, currlen, maxlen, '\0'); 642e1051a39Sopenharmony_ci return 0; 643e1051a39Sopenharmony_ci } 644e1051a39Sopenharmony_ci } else { 645e1051a39Sopenharmony_ci /* 646e1051a39Sopenharmony_ci * In E_FORMAT there is always one significant digit in front 647e1051a39Sopenharmony_ci * of the decimal point, so: 648e1051a39Sopenharmony_ci * significant digits == 1 + decimal places 649e1051a39Sopenharmony_ci */ 650e1051a39Sopenharmony_ci max--; 651e1051a39Sopenharmony_ci } 652e1051a39Sopenharmony_ci } 653e1051a39Sopenharmony_ci if (realstyle == E_FORMAT) 654e1051a39Sopenharmony_ci fvalue = tmpvalue; 655e1051a39Sopenharmony_ci } 656e1051a39Sopenharmony_ci ufvalue = abs_val(fvalue); 657e1051a39Sopenharmony_ci /* 658e1051a39Sopenharmony_ci * By subtracting 65535 (2^16-1) we cancel the low order 15 bits 659e1051a39Sopenharmony_ci * of ULONG_MAX to avoid using imprecise floating point values. 660e1051a39Sopenharmony_ci */ 661e1051a39Sopenharmony_ci if (ufvalue >= (double)(ULONG_MAX - 65535) + 65536.0) { 662e1051a39Sopenharmony_ci /* Number too big */ 663e1051a39Sopenharmony_ci (void)doapr_outch(sbuffer, buffer, currlen, maxlen, '\0'); 664e1051a39Sopenharmony_ci return 0; 665e1051a39Sopenharmony_ci } 666e1051a39Sopenharmony_ci intpart = (unsigned long)ufvalue; 667e1051a39Sopenharmony_ci 668e1051a39Sopenharmony_ci /* 669e1051a39Sopenharmony_ci * sorry, we only support 9 digits past the decimal because of our 670e1051a39Sopenharmony_ci * conversion method 671e1051a39Sopenharmony_ci */ 672e1051a39Sopenharmony_ci if (max > 9) 673e1051a39Sopenharmony_ci max = 9; 674e1051a39Sopenharmony_ci 675e1051a39Sopenharmony_ci /* 676e1051a39Sopenharmony_ci * we "cheat" by converting the fractional part to integer by multiplying 677e1051a39Sopenharmony_ci * by a factor of 10 678e1051a39Sopenharmony_ci */ 679e1051a39Sopenharmony_ci max10 = roundv(pow_10(max)); 680e1051a39Sopenharmony_ci fracpart = roundv(pow_10(max) * (ufvalue - intpart)); 681e1051a39Sopenharmony_ci 682e1051a39Sopenharmony_ci if (fracpart >= max10) { 683e1051a39Sopenharmony_ci intpart++; 684e1051a39Sopenharmony_ci fracpart -= max10; 685e1051a39Sopenharmony_ci } 686e1051a39Sopenharmony_ci 687e1051a39Sopenharmony_ci /* convert integer part */ 688e1051a39Sopenharmony_ci do { 689e1051a39Sopenharmony_ci iconvert[iplace++] = "0123456789"[intpart % 10]; 690e1051a39Sopenharmony_ci intpart = (intpart / 10); 691e1051a39Sopenharmony_ci } while (intpart && (iplace < (int)sizeof(iconvert))); 692e1051a39Sopenharmony_ci if (iplace == sizeof(iconvert)) 693e1051a39Sopenharmony_ci iplace--; 694e1051a39Sopenharmony_ci iconvert[iplace] = 0; 695e1051a39Sopenharmony_ci 696e1051a39Sopenharmony_ci /* convert fractional part */ 697e1051a39Sopenharmony_ci while (fplace < max) { 698e1051a39Sopenharmony_ci if (style == G_FORMAT && fplace == 0 && (fracpart % 10) == 0) { 699e1051a39Sopenharmony_ci /* We strip trailing zeros in G_FORMAT */ 700e1051a39Sopenharmony_ci max--; 701e1051a39Sopenharmony_ci fracpart = fracpart / 10; 702e1051a39Sopenharmony_ci if (fplace < max) 703e1051a39Sopenharmony_ci continue; 704e1051a39Sopenharmony_ci break; 705e1051a39Sopenharmony_ci } 706e1051a39Sopenharmony_ci fconvert[fplace++] = "0123456789"[fracpart % 10]; 707e1051a39Sopenharmony_ci fracpart = (fracpart / 10); 708e1051a39Sopenharmony_ci } 709e1051a39Sopenharmony_ci 710e1051a39Sopenharmony_ci if (fplace == sizeof(fconvert)) 711e1051a39Sopenharmony_ci fplace--; 712e1051a39Sopenharmony_ci fconvert[fplace] = 0; 713e1051a39Sopenharmony_ci 714e1051a39Sopenharmony_ci /* convert exponent part */ 715e1051a39Sopenharmony_ci if (realstyle == E_FORMAT) { 716e1051a39Sopenharmony_ci int tmpexp; 717e1051a39Sopenharmony_ci if (exp < 0) 718e1051a39Sopenharmony_ci tmpexp = -exp; 719e1051a39Sopenharmony_ci else 720e1051a39Sopenharmony_ci tmpexp = exp; 721e1051a39Sopenharmony_ci 722e1051a39Sopenharmony_ci do { 723e1051a39Sopenharmony_ci econvert[eplace++] = "0123456789"[tmpexp % 10]; 724e1051a39Sopenharmony_ci tmpexp = (tmpexp / 10); 725e1051a39Sopenharmony_ci } while (tmpexp > 0 && eplace < (int)sizeof(econvert)); 726e1051a39Sopenharmony_ci /* Exponent is huge!! Too big to print */ 727e1051a39Sopenharmony_ci if (tmpexp > 0) { 728e1051a39Sopenharmony_ci (void)doapr_outch(sbuffer, buffer, currlen, maxlen, '\0'); 729e1051a39Sopenharmony_ci return 0; 730e1051a39Sopenharmony_ci } 731e1051a39Sopenharmony_ci /* Add a leading 0 for single digit exponents */ 732e1051a39Sopenharmony_ci if (eplace == 1) 733e1051a39Sopenharmony_ci econvert[eplace++] = '0'; 734e1051a39Sopenharmony_ci } 735e1051a39Sopenharmony_ci 736e1051a39Sopenharmony_ci /* 737e1051a39Sopenharmony_ci * -1 for decimal point (if we have one, i.e. max > 0), 738e1051a39Sopenharmony_ci * another -1 if we are printing a sign 739e1051a39Sopenharmony_ci */ 740e1051a39Sopenharmony_ci padlen = min - iplace - max - (max > 0 ? 1 : 0) - ((signvalue) ? 1 : 0); 741e1051a39Sopenharmony_ci /* Take some off for exponent prefix "+e" and exponent */ 742e1051a39Sopenharmony_ci if (realstyle == E_FORMAT) 743e1051a39Sopenharmony_ci padlen -= 2 + eplace; 744e1051a39Sopenharmony_ci zpadlen = max - fplace; 745e1051a39Sopenharmony_ci if (zpadlen < 0) 746e1051a39Sopenharmony_ci zpadlen = 0; 747e1051a39Sopenharmony_ci if (padlen < 0) 748e1051a39Sopenharmony_ci padlen = 0; 749e1051a39Sopenharmony_ci if (flags & DP_F_MINUS) 750e1051a39Sopenharmony_ci padlen = -padlen; 751e1051a39Sopenharmony_ci 752e1051a39Sopenharmony_ci if ((flags & DP_F_ZERO) && (padlen > 0)) { 753e1051a39Sopenharmony_ci if (signvalue) { 754e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) 755e1051a39Sopenharmony_ci return 0; 756e1051a39Sopenharmony_ci --padlen; 757e1051a39Sopenharmony_ci signvalue = 0; 758e1051a39Sopenharmony_ci } 759e1051a39Sopenharmony_ci while (padlen > 0) { 760e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) 761e1051a39Sopenharmony_ci return 0; 762e1051a39Sopenharmony_ci --padlen; 763e1051a39Sopenharmony_ci } 764e1051a39Sopenharmony_ci } 765e1051a39Sopenharmony_ci while (padlen > 0) { 766e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 767e1051a39Sopenharmony_ci return 0; 768e1051a39Sopenharmony_ci --padlen; 769e1051a39Sopenharmony_ci } 770e1051a39Sopenharmony_ci if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) 771e1051a39Sopenharmony_ci return 0; 772e1051a39Sopenharmony_ci 773e1051a39Sopenharmony_ci while (iplace > 0) { 774e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace])) 775e1051a39Sopenharmony_ci return 0; 776e1051a39Sopenharmony_ci } 777e1051a39Sopenharmony_ci 778e1051a39Sopenharmony_ci /* 779e1051a39Sopenharmony_ci * Decimal point. This should probably use locale to find the correct 780e1051a39Sopenharmony_ci * char to print out. 781e1051a39Sopenharmony_ci */ 782e1051a39Sopenharmony_ci if (max > 0 || (flags & DP_F_NUM)) { 783e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.')) 784e1051a39Sopenharmony_ci return 0; 785e1051a39Sopenharmony_ci 786e1051a39Sopenharmony_ci while (fplace > 0) { 787e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, currlen, maxlen, 788e1051a39Sopenharmony_ci fconvert[--fplace])) 789e1051a39Sopenharmony_ci return 0; 790e1051a39Sopenharmony_ci } 791e1051a39Sopenharmony_ci } 792e1051a39Sopenharmony_ci while (zpadlen > 0) { 793e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) 794e1051a39Sopenharmony_ci return 0; 795e1051a39Sopenharmony_ci --zpadlen; 796e1051a39Sopenharmony_ci } 797e1051a39Sopenharmony_ci if (realstyle == E_FORMAT) { 798e1051a39Sopenharmony_ci char ech; 799e1051a39Sopenharmony_ci 800e1051a39Sopenharmony_ci if ((flags & DP_F_UP) == 0) 801e1051a39Sopenharmony_ci ech = 'e'; 802e1051a39Sopenharmony_ci else 803e1051a39Sopenharmony_ci ech = 'E'; 804e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ech)) 805e1051a39Sopenharmony_ci return 0; 806e1051a39Sopenharmony_ci if (exp < 0) { 807e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '-')) 808e1051a39Sopenharmony_ci return 0; 809e1051a39Sopenharmony_ci } else { 810e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '+')) 811e1051a39Sopenharmony_ci return 0; 812e1051a39Sopenharmony_ci } 813e1051a39Sopenharmony_ci while (eplace > 0) { 814e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, currlen, maxlen, 815e1051a39Sopenharmony_ci econvert[--eplace])) 816e1051a39Sopenharmony_ci return 0; 817e1051a39Sopenharmony_ci } 818e1051a39Sopenharmony_ci } 819e1051a39Sopenharmony_ci 820e1051a39Sopenharmony_ci while (padlen < 0) { 821e1051a39Sopenharmony_ci if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 822e1051a39Sopenharmony_ci return 0; 823e1051a39Sopenharmony_ci ++padlen; 824e1051a39Sopenharmony_ci } 825e1051a39Sopenharmony_ci return 1; 826e1051a39Sopenharmony_ci} 827e1051a39Sopenharmony_ci 828e1051a39Sopenharmony_ci#endif /* OPENSSL_SYS_UEFI */ 829e1051a39Sopenharmony_ci 830e1051a39Sopenharmony_ci#define BUFFER_INC 1024 831e1051a39Sopenharmony_ci 832e1051a39Sopenharmony_cistatic int 833e1051a39Sopenharmony_cidoapr_outch(char **sbuffer, 834e1051a39Sopenharmony_ci char **buffer, size_t *currlen, size_t *maxlen, int c) 835e1051a39Sopenharmony_ci{ 836e1051a39Sopenharmony_ci /* If we haven't at least one buffer, someone has done a big booboo */ 837e1051a39Sopenharmony_ci if (!ossl_assert(*sbuffer != NULL || buffer != NULL)) 838e1051a39Sopenharmony_ci return 0; 839e1051a39Sopenharmony_ci 840e1051a39Sopenharmony_ci /* |currlen| must always be <= |*maxlen| */ 841e1051a39Sopenharmony_ci if (!ossl_assert(*currlen <= *maxlen)) 842e1051a39Sopenharmony_ci return 0; 843e1051a39Sopenharmony_ci 844e1051a39Sopenharmony_ci if (buffer && *currlen == *maxlen) { 845e1051a39Sopenharmony_ci if (*maxlen > INT_MAX - BUFFER_INC) 846e1051a39Sopenharmony_ci return 0; 847e1051a39Sopenharmony_ci 848e1051a39Sopenharmony_ci *maxlen += BUFFER_INC; 849e1051a39Sopenharmony_ci if (*buffer == NULL) { 850e1051a39Sopenharmony_ci if ((*buffer = OPENSSL_malloc(*maxlen)) == NULL) { 851e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); 852e1051a39Sopenharmony_ci return 0; 853e1051a39Sopenharmony_ci } 854e1051a39Sopenharmony_ci if (*currlen > 0) { 855e1051a39Sopenharmony_ci if (!ossl_assert(*sbuffer != NULL)) 856e1051a39Sopenharmony_ci return 0; 857e1051a39Sopenharmony_ci memcpy(*buffer, *sbuffer, *currlen); 858e1051a39Sopenharmony_ci } 859e1051a39Sopenharmony_ci *sbuffer = NULL; 860e1051a39Sopenharmony_ci } else { 861e1051a39Sopenharmony_ci char *tmpbuf; 862e1051a39Sopenharmony_ci 863e1051a39Sopenharmony_ci tmpbuf = OPENSSL_realloc(*buffer, *maxlen); 864e1051a39Sopenharmony_ci if (tmpbuf == NULL) { 865e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); 866e1051a39Sopenharmony_ci return 0; 867e1051a39Sopenharmony_ci } 868e1051a39Sopenharmony_ci *buffer = tmpbuf; 869e1051a39Sopenharmony_ci } 870e1051a39Sopenharmony_ci } 871e1051a39Sopenharmony_ci 872e1051a39Sopenharmony_ci if (*currlen < *maxlen) { 873e1051a39Sopenharmony_ci if (*sbuffer) 874e1051a39Sopenharmony_ci (*sbuffer)[(*currlen)++] = (char)c; 875e1051a39Sopenharmony_ci else 876e1051a39Sopenharmony_ci (*buffer)[(*currlen)++] = (char)c; 877e1051a39Sopenharmony_ci } 878e1051a39Sopenharmony_ci 879e1051a39Sopenharmony_ci return 1; 880e1051a39Sopenharmony_ci} 881e1051a39Sopenharmony_ci 882e1051a39Sopenharmony_ci/***************************************************************************/ 883e1051a39Sopenharmony_ci 884e1051a39Sopenharmony_ciint BIO_printf(BIO *bio, const char *format, ...) 885e1051a39Sopenharmony_ci{ 886e1051a39Sopenharmony_ci va_list args; 887e1051a39Sopenharmony_ci int ret; 888e1051a39Sopenharmony_ci 889e1051a39Sopenharmony_ci va_start(args, format); 890e1051a39Sopenharmony_ci 891e1051a39Sopenharmony_ci ret = BIO_vprintf(bio, format, args); 892e1051a39Sopenharmony_ci 893e1051a39Sopenharmony_ci va_end(args); 894e1051a39Sopenharmony_ci return ret; 895e1051a39Sopenharmony_ci} 896e1051a39Sopenharmony_ci 897e1051a39Sopenharmony_ciint BIO_vprintf(BIO *bio, const char *format, va_list args) 898e1051a39Sopenharmony_ci{ 899e1051a39Sopenharmony_ci int ret; 900e1051a39Sopenharmony_ci size_t retlen; 901e1051a39Sopenharmony_ci char hugebuf[1024 * 2]; /* Was previously 10k, which is unreasonable 902e1051a39Sopenharmony_ci * in small-stack environments, like threads 903e1051a39Sopenharmony_ci * or DOS programs. */ 904e1051a39Sopenharmony_ci char *hugebufp = hugebuf; 905e1051a39Sopenharmony_ci size_t hugebufsize = sizeof(hugebuf); 906e1051a39Sopenharmony_ci char *dynbuf = NULL; 907e1051a39Sopenharmony_ci int ignored; 908e1051a39Sopenharmony_ci 909e1051a39Sopenharmony_ci dynbuf = NULL; 910e1051a39Sopenharmony_ci if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format, 911e1051a39Sopenharmony_ci args)) { 912e1051a39Sopenharmony_ci OPENSSL_free(dynbuf); 913e1051a39Sopenharmony_ci return -1; 914e1051a39Sopenharmony_ci } 915e1051a39Sopenharmony_ci if (dynbuf) { 916e1051a39Sopenharmony_ci ret = BIO_write(bio, dynbuf, (int)retlen); 917e1051a39Sopenharmony_ci OPENSSL_free(dynbuf); 918e1051a39Sopenharmony_ci } else { 919e1051a39Sopenharmony_ci ret = BIO_write(bio, hugebuf, (int)retlen); 920e1051a39Sopenharmony_ci } 921e1051a39Sopenharmony_ci return ret; 922e1051a39Sopenharmony_ci} 923e1051a39Sopenharmony_ci 924e1051a39Sopenharmony_ci/* 925e1051a39Sopenharmony_ci * As snprintf is not available everywhere, we provide our own 926e1051a39Sopenharmony_ci * implementation. This function has nothing to do with BIOs, but it's 927e1051a39Sopenharmony_ci * closely related to BIO_printf, and we need *some* name prefix ... (XXX the 928e1051a39Sopenharmony_ci * function should be renamed, but to what?) 929e1051a39Sopenharmony_ci */ 930e1051a39Sopenharmony_ciint BIO_snprintf(char *buf, size_t n, const char *format, ...) 931e1051a39Sopenharmony_ci{ 932e1051a39Sopenharmony_ci va_list args; 933e1051a39Sopenharmony_ci int ret; 934e1051a39Sopenharmony_ci 935e1051a39Sopenharmony_ci va_start(args, format); 936e1051a39Sopenharmony_ci 937e1051a39Sopenharmony_ci ret = BIO_vsnprintf(buf, n, format, args); 938e1051a39Sopenharmony_ci 939e1051a39Sopenharmony_ci va_end(args); 940e1051a39Sopenharmony_ci return ret; 941e1051a39Sopenharmony_ci} 942e1051a39Sopenharmony_ci 943e1051a39Sopenharmony_ciint BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) 944e1051a39Sopenharmony_ci{ 945e1051a39Sopenharmony_ci size_t retlen; 946e1051a39Sopenharmony_ci int truncated; 947e1051a39Sopenharmony_ci 948e1051a39Sopenharmony_ci if (!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args)) 949e1051a39Sopenharmony_ci return -1; 950e1051a39Sopenharmony_ci 951e1051a39Sopenharmony_ci if (truncated) 952e1051a39Sopenharmony_ci /* 953e1051a39Sopenharmony_ci * In case of truncation, return -1 like traditional snprintf. 954e1051a39Sopenharmony_ci * (Current drafts for ISO/IEC 9899 say snprintf should return the 955e1051a39Sopenharmony_ci * number of characters that would have been written, had the buffer 956e1051a39Sopenharmony_ci * been large enough.) 957e1051a39Sopenharmony_ci */ 958e1051a39Sopenharmony_ci return -1; 959e1051a39Sopenharmony_ci return (retlen <= INT_MAX) ? (int)retlen : -1; 960e1051a39Sopenharmony_ci} 961