[edk2-devel] [PATCH] CryptoPkg: Add b_print.c which removed floating-point to OpensslLib

Yao, Jiewen jiewen.yao at intel.com
Sun Nov 20 02:18:36 UTC 2022


HI Yi
I have question for 1 - The original file uses code related to floating-point and ulldrvm.

a) Openssl supports OPENSSL_SYS_UEFI macro (https://github.com/tianocore/edk2/blob/master/CryptoPkg/Library/Include/openssl/opensslconf.h#L28), why not use OPENSSL_SYS_UEFI macro to eliminate float point action?

b) For ulldrvm, why not implement it in https://github.com/tianocore/edk2/tree/master/CryptoPkg/Library/IntrinsicLib, as we already did.

Thank you
Yao, Jiewen

> -----Original Message-----
> From: Li, Yi1 <yi1.li at intel.com>
> Sent: Sunday, November 20, 2022 12:33 AM
> To: devel at edk2.groups.io
> Cc: Yao, Jiewen <jiewen.yao at intel.com>; Wang, Jian J
> <jian.j.wang at intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu at intel.com>; Jiang,
> Guomin <guomin.jiang at intel.com>
> Subject: RE: [PATCH] CryptoPkg: Add b_print.c which removed floating-
> point to OpensslLib
> 
> Hi all,
> 
> This patch is the pre-work for enabling the X509 certificate time check.
> I know it looks weird to add a new b_print.c, so I wanted to explain the
> background of this patch.
> 
> 1. Why not directly use the b_print.c file in openssl?
> The original file uses code related to floating-point and ulldrvm, which will
> cause compilation errors like:
> unresolved external symbol __aulldvrm
> error: SSE register return with SSE disabled
> ref: https://github.com/tianocore/edk2/pull/3508
> 
> So I removed all float code and replaced ulldrvm with
> DivU64x32Remainder():
> 1).
>             case 'f':
>             case 'E':
>             case 'e':
>             case 'G':
>             case 'g':
>                 return -1;
> 2).
> +        uvalue = DivU64x32Remainder(uvalue, (unsigned)base, &uremainder);
>          convert[place++] = (caps ? "0123456789ABCDEF" :
> "0123456789abcdef")
> -            [uvalue % (unsigned)base];
> -        uvalue = (uvalue / (unsigned)base);
> +            [uremainder];
> 
> 
> 2. Why not use the similar print function AsciiVSPrint in EDK2?
> EDK2 functions are all ms_abi but openssl functions not, so they use
> different va_list definitions, the relevant codes are as follows:
> GCC:*_*_X64_CC_FLAGS     = ......  -DNO_MSABI_VA_FUNCS
> https://github.com/tianocore/edk2/blob/fff6d81270b57ee786ea18ad74f4
> 3149b9f03494/CryptoPkg/Library/OpensslLib/OpensslLib.inf#LL636C2-
> L636C3
> 
> Therefore, segmentation fault will occur when calling the edk2 VA
> parameter function in the openssl function.
> 
> 3. Why not remove NO_MSABI_VA_FUNCS?
> Similarly, ms va_list cannot be used in the sysv function in openssl, which
> will also cause segmentation fault.
> 
> I am not expert of compilation, let me know if there is other better idea.
> 
> Thanks,
> Yi
> 
> -----Original Message-----
> From: Li, Yi1 <yi1.li at intel.com>
> Sent: Sunday, November 20, 2022 12:28 AM
> To: devel at edk2.groups.io
> Cc: Li, Yi1 <yi1.li at intel.com>; Yao, Jiewen <jiewen.yao at intel.com>; Wang,
> Jian J <jian.j.wang at intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu at intel.com>; Jiang,
> Guomin <guomin.jiang at intel.com>
> Subject: [PATCH] CryptoPkg: Add b_print.c which removed floating-point to
> OpensslLib
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4110
> 
> Openssl will use BIO_snprintf() to print time string when converting time_t
> to ASN1_time.
> Currently edk2 code just give it a NULL implement in CrtWrapper.c, so
> getting current time in X509 time check will be fail.
> 
> This patch add a copy of OpensslLib\openssl\crypto\bio\b_print.c to
> OpensslLib, with below changes:
> 
> 1. All floating point related code removed.
> 2. Replace ull divide and remainder with DivU64x32Remainder().
> 
> Cc: Jiewen Yao <jiewen.yao at intel.com>
> Cc: Jian J Wang <jian.j.wang at intel.com>
> Cc: Xiaoyu Lu <xiaoyu1.lu at intel.com>
> Cc: Guomin Jiang <guomin.jiang at intel.com>
> Signed-off-by: Yi Li <yi1.li at intel.com>
> ---
>  CryptoPkg/CryptoPkg.ci.yaml                   |   4 +-
>  .../Library/BaseCryptLib/SysCall/CrtWrapper.c |  27 -
>  .../SysCall/UnitTestHostCrtWrapper.c          |  25 -
>  CryptoPkg/Library/OpensslLib/OpensslLib.inf   |   1 +
>  .../Library/OpensslLib/OpensslLibAccel.inf    |   1 +
>  .../Library/OpensslLib/OpensslLibCrypto.inf   |   1 +
>  .../Library/OpensslLib/OpensslLibFull.inf     |   1 +
>  .../OpensslLib/OpensslLibFullAccel.inf        |   1 +
>  CryptoPkg/Library/OpensslLib/b_print.c        | 613 ++++++++++++++++++
>  9 files changed, 621 insertions(+), 53 deletions(-)  create mode 100644
> CryptoPkg/Library/OpensslLib/b_print.c
> 
> diff --git a/CryptoPkg/CryptoPkg.ci.yaml b/CryptoPkg/CryptoPkg.ci.yaml
> index 47f2975967..8c25f581fb 100644
> --- a/CryptoPkg/CryptoPkg.ci.yaml
> +++ b/CryptoPkg/CryptoPkg.ci.yaml
> @@ -13,7 +13,9 @@
>              "Library/OpensslLib/IA32Gcc",
>              "Library/OpensslLib/X64",
>              "Library/OpensslLib/X64Gcc",
> -            "Library/Include/openssl"
> +            "Library/Include/openssl",
> +            # b_print.c is a copy from OpenSSl.
> +            "Library/OpensslLib/b_print.c"
>          ]
>      },
>      "EccCheck": {
> diff --git a/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
> b/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
> index b65d29485b..6d7ac3efdc 100644
> --- a/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
> +++ b/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
> @@ -472,33 +472,6 @@ fwrite (
>    return 0;
>  }
> 
> -//
> -//  -- Dummy OpenSSL Support Routines -- -//
> -
> -int
> -BIO_printf (
> -  void        *bio,
> -  const char  *format,
> -  ...
> -  )
> -{
> -  return 0;
> -}
> -
> -int
> -BIO_snprintf (
> -  char        *buf,
> -  size_t      n,
> -  const char  *format,
> -  ...
> -  )
> -{
> -  // Because the function does not actually print anything to buf, it returns
> -1 as error.
> -  // Otherwise, the consumer may think that the buf is valid and parse the
> buffer.
> -  return -1;
> -}
> -
>  #ifdef __GNUC__
> 
>  typedef
> diff --git
> a/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c
> b/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c
> index 066d53e4fa..244e57437e 100644
> --- a/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c
> +++ b/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c
> @@ -72,31 +72,6 @@ sscanf (
>    return 0;
>  }
> 
> -//
> -//  -- Dummy OpenSSL Support Routines -- -//
> -
> -int
> -BIO_printf (
> -  void        *bio,
> -  const char  *format,
> -  ...
> -  )
> -{
> -  return 0;
> -}
> -
> -int
> -BIO_snprintf (
> -  char        *buf,
> -  size_t      n,
> -  const char  *format,
> -  ...
> -  )
> -{
> -  return 0;
> -}
> -
>  uid_t
>  getuid (
>    void
> diff --git a/CryptoPkg/Library/OpensslLib/OpensslLib.inf
> b/CryptoPkg/Library/OpensslLib/OpensslLib.inf
> index 60c6c24b0a..f8ddfadc51 100644
> --- a/CryptoPkg/Library/OpensslLib/OpensslLib.inf
> +++ b/CryptoPkg/Library/OpensslLib/OpensslLib.inf
> @@ -580,6 +580,7 @@
>    rand_pool.c
>  #  SslNull.c
>    EcSm2Null.c
> +  b_print.c
> 
>  [Packages]
>    MdePkg/MdePkg.dec
> diff --git a/CryptoPkg/Library/OpensslLib/OpensslLibAccel.inf
> b/CryptoPkg/Library/OpensslLib/OpensslLibAccel.inf
> index 103ef7bda2..6ee7bfd329 100644
> --- a/CryptoPkg/Library/OpensslLib/OpensslLibAccel.inf
> +++ b/CryptoPkg/Library/OpensslLib/OpensslLibAccel.inf
> @@ -580,6 +580,7 @@
>    rand_pool.c
>  #  SslNull.c
>    EcSm2Null.c
> +  b_print.c
> 
>  [Sources.IA32]
>  # Autogenerated IA32 files list starts here diff --git
> a/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
> b/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
> index c4eaea888c..3e43cf146b 100644
> --- a/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
> +++ b/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
> @@ -530,6 +530,7 @@
>    rand_pool.c
>    SslNull.c
>    EcSm2Null.c
> +  b_print.c
> 
>  [Packages]
>    MdePkg/MdePkg.dec
> diff --git a/CryptoPkg/Library/OpensslLib/OpensslLibFull.inf
> b/CryptoPkg/Library/OpensslLib/OpensslLibFull.inf
> index 309e43055c..440d3e7e1d 100644
> --- a/CryptoPkg/Library/OpensslLib/OpensslLibFull.inf
> +++ b/CryptoPkg/Library/OpensslLib/OpensslLibFull.inf
> @@ -635,6 +635,7 @@
>    rand_pool.c
>  #  SslNull.c
>  #  EcSm2Null.c
> +  b_print.c
> 
>  [Packages]
>    MdePkg/MdePkg.dec
> diff --git a/CryptoPkg/Library/OpensslLib/OpensslLibFullAccel.inf
> b/CryptoPkg/Library/OpensslLib/OpensslLibFullAccel.inf
> index 4eeeeb79bd..413f70f733 100644
> --- a/CryptoPkg/Library/OpensslLib/OpensslLibFullAccel.inf
> +++ b/CryptoPkg/Library/OpensslLib/OpensslLibFullAccel.inf
> @@ -635,6 +635,7 @@
>    rand_pool.c
>  #  SslNull.c
>  #  EcSm2Null.c
> +  b_print.c
> 
>  [Sources.IA32]
>  # Autogenerated IA32 files list starts here diff --git
> a/CryptoPkg/Library/OpensslLib/b_print.c
> b/CryptoPkg/Library/OpensslLib/b_print.c
> new file mode 100644
> index 0000000000..885c3b9264
> --- /dev/null
> +++ b/CryptoPkg/Library/OpensslLib/b_print.c
> @@ -0,0 +1,613 @@
> +/*
> + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
> + *
> + * Licensed under the OpenSSL license (the "License").  You may not use
> + * this file except in compliance with the License.  You can obtain a
> +copy
> + * in the file LICENSE in the source distribution or at
> + * https://www.openssl.org/source/license.html
> + *
> + * Please notes:
> + * This file is a copy of OpensslLib\openssl\crypto\bio\b_print.c
> + * with all floating point related code removed (Not supported in UEFI).
> + * This means that '%f' '%g' '%e' and related combined formats are no
> longer supported.
> + *
> + */
> +
> +#include <stdio.h>
> +#include <string.h>
> +#include "internal/cryptlib.h"
> +#include "crypto/ctype.h"
> +#include "internal/numbers.h"
> +#include <openssl/bio.h>
> +
> +/*
> + * Copyright Patrick Powell 1995
> + * This code is based on code written by Patrick Powell
> +<papowell at astart.com>
> + * It may be used for any purpose as long as this notice remains intact
> + * on all source code distributions.
> + */
> +
> +static int fmtstr(char **, char **, size_t *, size_t *,
> +                  const char *, int, int, int); static int fmtint(char
> +**, char **, size_t *, size_t *,
> +                  int64_t, int, int, int, int); static int
> +doapr_outch(char **, char **, size_t *, size_t *, int); static int
> +_dopr(char **sbuffer, char **buffer,
> +                 size_t *maxlen, size_t *retlen, int *truncated,
> +                 const char *format, va_list args);
> +
> +/* format read states */
> +#define DP_S_DEFAULT    0
> +#define DP_S_FLAGS      1
> +#define DP_S_MIN        2
> +#define DP_S_DOT        3
> +#define DP_S_MAX        4
> +#define DP_S_MOD        5
> +#define DP_S_CONV       6
> +#define DP_S_DONE       7
> +
> +/* format flags - Bits */
> +/* left-aligned padding */
> +#define DP_F_MINUS      (1 << 0)
> +/* print an explicit '+' for a value with positive sign */
> +#define DP_F_PLUS       (1 << 1)
> +/* print an explicit ' ' for a value with positive sign */
> +#define DP_F_SPACE      (1 << 2)
> +/* print 0/0x prefix for octal/hex and decimal point for floating point */
> +#define DP_F_NUM        (1 << 3)
> +/* print leading zeroes */
> +#define DP_F_ZERO       (1 << 4)
> +/* print HEX in UPPPERcase */
> +#define DP_F_UP         (1 << 5)
> +/* treat value as unsigned */
> +#define DP_F_UNSIGNED   (1 << 6)
> +
> +/* conversion flags */
> +#define DP_C_SHORT      1
> +#define DP_C_LONG       2
> +// #define DP_C_LDOUBLE    3
> +#define DP_C_LLONG      4
> +#define DP_C_SIZE       5
> +
> +/* Floating point formats */
> +// #define F_FORMAT        0
> +// #define E_FORMAT        1
> +// #define G_FORMAT        2
> +
> +/* some handy macros */
> +#define char_to_int(p) (p - '0')
> +#define OSSL_MAX(p,q) ((p >= q) ? p : q)
> +
> +static int
> +_dopr(char **sbuffer,
> +      char **buffer,
> +      size_t *maxlen,
> +      size_t *retlen, int *truncated, const char *format, va_list args)
> +{
> +    char ch;
> +    int64_t value;
> +    char *strvalue;
> +    int min;
> +    int max;
> +    int state;
> +    int flags;
> +    int cflags;
> +    size_t currlen;
> +
> +    state = DP_S_DEFAULT;
> +    flags = currlen = cflags = min = 0;
> +    max = -1;
> +    ch = *format++;
> +
> +    while (state != DP_S_DONE) {
> +        if (ch == '\0' || (buffer == NULL && currlen >= *maxlen))
> +            state = DP_S_DONE;
> +
> +        switch (state) {
> +        case DP_S_DEFAULT:
> +            if (ch == '%')
> +                state = DP_S_FLAGS;
> +            else
> +                if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
> +                    return 0;
> +            ch = *format++;
> +            break;
> +        case DP_S_FLAGS:
> +            switch (ch) {
> +            case '-':
> +                flags |= DP_F_MINUS;
> +                ch = *format++;
> +                break;
> +            case '+':
> +                flags |= DP_F_PLUS;
> +                ch = *format++;
> +                break;
> +            case ' ':
> +                flags |= DP_F_SPACE;
> +                ch = *format++;
> +                break;
> +            case '#':
> +                flags |= DP_F_NUM;
> +                ch = *format++;
> +                break;
> +            case '0':
> +                flags |= DP_F_ZERO;
> +                ch = *format++;
> +                break;
> +            default:
> +                state = DP_S_MIN;
> +                break;
> +            }
> +            break;
> +        case DP_S_MIN:
> +            if (ossl_isdigit(ch)) {
> +                min = 10 * min + char_to_int(ch);
> +                ch = *format++;
> +            } else if (ch == '*') {
> +                min = va_arg(args, int);
> +                ch = *format++;
> +                state = DP_S_DOT;
> +            } else
> +                state = DP_S_DOT;
> +            break;
> +        case DP_S_DOT:
> +            if (ch == '.') {
> +                state = DP_S_MAX;
> +                ch = *format++;
> +            } else
> +                state = DP_S_MOD;
> +            break;
> +        case DP_S_MAX:
> +            if (ossl_isdigit(ch)) {
> +                if (max < 0)
> +                    max = 0;
> +                max = 10 * max + char_to_int(ch);
> +                ch = *format++;
> +            } else if (ch == '*') {
> +                max = va_arg(args, int);
> +                ch = *format++;
> +                state = DP_S_MOD;
> +            } else
> +                state = DP_S_MOD;
> +            break;
> +        case DP_S_MOD:
> +            switch (ch) {
> +            case 'h':
> +                cflags = DP_C_SHORT;
> +                ch = *format++;
> +                break;
> +            case 'l':
> +                if (*format == 'l') {
> +                    cflags = DP_C_LLONG;
> +                    format++;
> +                } else
> +                    cflags = DP_C_LONG;
> +                ch = *format++;
> +                break;
> +            case 'q':
> +            case 'j':
> +                cflags = DP_C_LLONG;
> +                ch = *format++;
> +                break;
> +            case 'L':
> +                //Unsupported fmt in UEFI
> +                return -1;
> +            case 'z':
> +                cflags = DP_C_SIZE;
> +                ch = *format++;
> +                break;
> +            default:
> +                break;
> +            }
> +            state = DP_S_CONV;
> +            break;
> +        case DP_S_CONV:
> +            switch (ch) {
> +            case 'd':
> +            case 'i':
> +                switch (cflags) {
> +                case DP_C_SHORT:
> +                    value = (short int)va_arg(args, int);
> +                    break;
> +                case DP_C_LONG:
> +                    value = va_arg(args, long int);
> +                    break;
> +                case DP_C_LLONG:
> +                    value = va_arg(args, int64_t);
> +                    break;
> +                case DP_C_SIZE:
> +                    value = va_arg(args, ossl_ssize_t);
> +                    break;
> +                default:
> +                    value = va_arg(args, int);
> +                    break;
> +                }
> +                if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min,
> +                            max, flags))
> +                    return 0;
> +                break;
> +            case 'X':
> +                flags |= DP_F_UP;
> +                /* FALLTHROUGH */
> +            case 'x':
> +            case 'o':
> +            case 'u':
> +                flags |= DP_F_UNSIGNED;
> +                switch (cflags) {
> +                case DP_C_SHORT:
> +                    value = (unsigned short int)va_arg(args, unsigned int);
> +                    break;
> +                case DP_C_LONG:
> +                    value = va_arg(args, unsigned long int);
> +                    break;
> +                case DP_C_LLONG:
> +                    value = va_arg(args, uint64_t);
> +                    break;
> +                case DP_C_SIZE:
> +                    value = va_arg(args, size_t);
> +                    break;
> +                default:
> +                    value = va_arg(args, unsigned int);
> +                    break;
> +                }
> +                if (!fmtint(sbuffer, buffer, &currlen, maxlen, value,
> +                            ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
> +                            min, max, flags))
> +                    return 0;
> +                break;
> +            case 'f':
> +            case 'E':
> +            case 'e':
> +            case 'G':
> +            case 'g':
> +                return -1;
> +            case 'c':
> +                if (!doapr_outch(sbuffer, buffer, &currlen, maxlen,
> +                                 va_arg(args, int)))
> +                    return 0;
> +                break;
> +            case 's':
> +                strvalue = va_arg(args, char *);
> +                if (max < 0) {
> +                    if (buffer)
> +                        max = INT_MAX;
> +                    else
> +                        max = *maxlen;
> +                }
> +                if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
> +                            flags, min, max))
> +                    return 0;
> +                break;
> +            case 'p':
> +                value = (size_t)va_arg(args, void *);
> +                if (!fmtint(sbuffer, buffer, &currlen, maxlen,
> +                            value, 16, min, max, flags | DP_F_NUM))
> +                    return 0;
> +                break;
> +            case 'n':
> +                {
> +                    int *num;
> +                    num = va_arg(args, int *);
> +                    *num = currlen;
> +                }
> +                break;
> +            case '%':
> +                if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
> +                    return 0;
> +                break;
> +            case 'w':
> +                /* not supported yet, treat as next char */
> +                ch = *format++;
> +                break;
> +            default:
> +                /* unknown, skip */
> +                break;
> +            }
> +            ch = *format++;
> +            state = DP_S_DEFAULT;
> +            flags = cflags = min = 0;
> +            max = -1;
> +            break;
> +        case DP_S_DONE:
> +            break;
> +        default:
> +            break;
> +        }
> +    }
> +    /*
> +     * We have to truncate if there is no dynamic buffer and we have filled
> the
> +     * static buffer.
> +     */
> +    if (buffer == NULL) {
> +        *truncated = (currlen > *maxlen - 1);
> +        if (*truncated)
> +            currlen = *maxlen - 1;
> +    }
> +    if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'))
> +        return 0;
> +    *retlen = currlen - 1;
> +    return 1;
> +}
> +
> +static int
> +fmtstr(char **sbuffer,
> +       char **buffer,
> +       size_t *currlen,
> +       size_t *maxlen, const char *value, int flags, int min, int max)
> +{
> +    int padlen;
> +    size_t strln;
> +    int cnt = 0;
> +
> +    if (value == 0)
> +        value = "<NULL>";
> +
> +    strln = OPENSSL_strnlen(value, max < 0 ? SIZE_MAX : (size_t)max);
> +
> +    padlen = min - strln;
> +    if (min < 0 || padlen < 0)
> +        padlen = 0;
> +    if (max >= 0) {
> +        /*
> +         * Calculate the maximum output including padding.
> +         * Make sure max doesn't overflow into negativity
> +         */
> +        if (max < INT_MAX - padlen)
> +            max += padlen;
> +        else
> +            max = INT_MAX;
> +    }
> +    if (flags & DP_F_MINUS)
> +        padlen = -padlen;
> +
> +    while ((padlen > 0) && (max < 0 || cnt < max)) {
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
> +            return 0;
> +        --padlen;
> +        ++cnt;
> +    }
> +    while (strln > 0 && (max < 0 || cnt < max)) {
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++))
> +            return 0;
> +        --strln;
> +        ++cnt;
> +    }
> +    while ((padlen < 0) && (max < 0 || cnt < max)) {
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
> +            return 0;
> +        ++padlen;
> +        ++cnt;
> +    }
> +    return 1;
> +}
> +
> +static int
> +fmtint(char **sbuffer,
> +       char **buffer,
> +       size_t *currlen,
> +       size_t *maxlen, int64_t value, int base, int min, int max, int
> +flags) {
> +    int signvalue = 0;
> +    const char *prefix = "";
> +    uint64_t uvalue;
> +    char convert[DECIMAL_SIZE(value) + 3];
> +    int place = 0;
> +    int spadlen = 0;
> +    int zpadlen = 0;
> +    int caps = 0;
> +    uint32_t uremainder = 0;
> +
> +    if (max < 0)
> +        max = 0;
> +    uvalue = value;
> +    if (!(flags & DP_F_UNSIGNED)) {
> +        if (value < 0) {
> +            signvalue = '-';
> +            uvalue = 0 - (uint64_t)value;
> +        } else if (flags & DP_F_PLUS)
> +            signvalue = '+';
> +        else if (flags & DP_F_SPACE)
> +            signvalue = ' ';
> +    }
> +    if (flags & DP_F_NUM) {
> +        if (base == 8)
> +            prefix = "0";
> +        if (base == 16)
> +            prefix = "0x";
> +    }
> +    if (flags & DP_F_UP)
> +        caps = 1;
> +    do {
> +        uvalue = DivU64x32Remainder(uvalue, (unsigned)base, &uremainder);
> +        convert[place++] = (caps ? "0123456789ABCDEF" :
> "0123456789abcdef")
> +            [uremainder];
> +    } while (uvalue && (place < (int)sizeof(convert)));
> +    if (place == sizeof(convert))
> +        place--;
> +    convert[place] = 0;
> +
> +    zpadlen = max - place;
> +    spadlen =
> +        min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix);
> +    if (zpadlen < 0)
> +        zpadlen = 0;
> +    if (spadlen < 0)
> +        spadlen = 0;
> +    if (flags & DP_F_ZERO) {
> +        zpadlen = OSSL_MAX(zpadlen, spadlen);
> +        spadlen = 0;
> +    }
> +    if (flags & DP_F_MINUS)
> +        spadlen = -spadlen;
> +
> +    /* spaces */
> +    while (spadlen > 0) {
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
> +            return 0;
> +        --spadlen;
> +    }
> +
> +    /* sign */
> +    if (signvalue)
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
> +            return 0;
> +
> +    /* prefix */
> +    while (*prefix) {
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix))
> +            return 0;
> +        prefix++;
> +    }
> +
> +    /* zeros */
> +    if (zpadlen > 0) {
> +        while (zpadlen > 0) {
> +            if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
> +                return 0;
> +            --zpadlen;
> +        }
> +    }
> +    /* digits */
> +    while (place > 0) {
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]))
> +            return 0;
> +    }
> +
> +    /* left justified spaces */
> +    while (spadlen < 0) {
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
> +            return 0;
> +        ++spadlen;
> +    }
> +    return 1;
> +}
> +
> +#define BUFFER_INC  1024
> +
> +static int
> +doapr_outch(char **sbuffer,
> +            char **buffer, size_t *currlen, size_t *maxlen, int c) {
> +    /* If we haven't at least one buffer, someone has done a big booboo */
> +    if (!ossl_assert(*sbuffer != NULL || buffer != NULL))
> +        return 0;
> +
> +    /* |currlen| must always be <= |*maxlen| */
> +    if (!ossl_assert(*currlen <= *maxlen))
> +        return 0;
> +
> +    if (buffer && *currlen == *maxlen) {
> +        if (*maxlen > INT_MAX - BUFFER_INC)
> +            return 0;
> +
> +        *maxlen += BUFFER_INC;
> +        if (*buffer == NULL) {
> +            if ((*buffer = OPENSSL_malloc(*maxlen)) == NULL) {
> +                BIOerr(BIO_F_DOAPR_OUTCH, ERR_R_MALLOC_FAILURE);
> +                return 0;
> +            }
> +            if (*currlen > 0) {
> +                if (!ossl_assert(*sbuffer != NULL))
> +                    return 0;
> +                memcpy(*buffer, *sbuffer, *currlen);
> +            }
> +            *sbuffer = NULL;
> +        } else {
> +            char *tmpbuf;
> +            tmpbuf = OPENSSL_realloc(*buffer, *maxlen);
> +            if (tmpbuf == NULL)
> +                return 0;
> +            *buffer = tmpbuf;
> +        }
> +    }
> +
> +    if (*currlen < *maxlen) {
> +        if (*sbuffer)
> +            (*sbuffer)[(*currlen)++] = (char)c;
> +        else
> +            (*buffer)[(*currlen)++] = (char)c;
> +    }
> +
> +    return 1;
> +}
> +
> +/*********************************************************
> *************
> +*****/
> +
> +int BIO_printf(BIO *bio, const char *format, ...) {
> +    va_list args;
> +    int ret;
> +
> +    va_start(args, format);
> +
> +    ret = BIO_vprintf(bio, format, args);
> +
> +    va_end(args);
> +    return ret;
> +}
> +
> +int BIO_vprintf(BIO *bio, const char *format, va_list args) {
> +    int ret;
> +    size_t retlen;
> +    char hugebuf[1024 * 2];     /* Was previously 10k, which is
> unreasonable
> +                                 * in small-stack environments, like threads
> +                                 * or DOS programs. */
> +    char *hugebufp = hugebuf;
> +    size_t hugebufsize = sizeof(hugebuf);
> +    char *dynbuf = NULL;
> +    int ignored;
> +
> +    dynbuf = NULL;
> +    if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored,
> format,
> +                args)) {
> +        OPENSSL_free(dynbuf);
> +        return -1;
> +    }
> +    if (dynbuf) {
> +        ret = BIO_write(bio, dynbuf, (int)retlen);
> +        OPENSSL_free(dynbuf);
> +    } else {
> +        ret = BIO_write(bio, hugebuf, (int)retlen);
> +    }
> +    return ret;
> +}
> +
> +/*
> + * As snprintf is not available everywhere, we provide our own
> + * implementation. This function has nothing to do with BIOs, but it's
> + * closely related to BIO_printf, and we need *some* name prefix ...
> +(XXX the
> + * function should be renamed, but to what?)  */ int BIO_snprintf(char
> +*buf, size_t n, const char *format, ...) {
> +    va_list args;
> +    int ret;
> +
> +    va_start(args, format);
> +
> +    ret = BIO_vsnprintf(buf, n, format, args);
> +
> +    va_end(args);
> +    return ret;
> +}
> +
> +int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list
> +args) {
> +    size_t retlen;
> +    int truncated;
> +
> +    if (!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args))
> +        return -1;
> +
> +    if (truncated)
> +        /*
> +         * In case of truncation, return -1 like traditional snprintf.
> +         * (Current drafts for ISO/IEC 9899 say snprintf should return the
> +         * number of characters that would have been written, had the buffer
> +         * been large enough.)
> +         */
> +        return -1;
> +    else
> +        return (retlen <= INT_MAX) ? (int)retlen : -1; }
> --
> 2.31.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#96505): https://edk2.groups.io/g/devel/message/96505
Mute This Topic: https://groups.io/mt/95135786/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-




More information about the edk2-devel-archive mailing list