[Openvpn-devel,v2] mingw: avoid C99 "hh" scanf length modifier

Message ID 20260708185659.10219-1-gert@greenie.muc.de
State New
Headers
Series [Openvpn-devel,v2] mingw: avoid C99 "hh" scanf length modifier |

Commit Message

Gert Doering July 8, 2026, 6:56 p.m. UTC
  From: Heiko Hund <heiko@ist.eigentlich.net>

read_key_file() and parse_hexstring() parse hex bytes with sscanf()
using the C99 "hh" length modifier, storing directly into an octet.

This is not portable to the legacy MSVCRT runtime that Ubuntu
resolute's (26.04) mingw toolchain links against.

Scan into an unsigned int and cast to the octet instead. The field width
caps the value at 0xFF, so the narrowing cast cannot lose data.

Change-Id: I6595695ab6401047d498d530f8739686880bea3a
Signed-off-by: Heiko Hund <heiko@ist.eigentlich.net>
Acked-by: Frank Lichtenheld <frank@lichtenheld.com>
Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1733
---

This change was reviewed on Gerrit and approved by at least one
developer. I request to merge it to master.

Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1733
This mail reflects revision 2 of this Change.

Acked-by according to Gerrit (reflected above):
Frank Lichtenheld <frank@lichtenheld.com>
  

Comments

Gert Doering July 23, 2026, 8:43 p.m. UTC | #1
I find the whole explanation behind this highly confusing, and I find it
even more amazing that we have no "parse_hex_byte_ex()" function in all
of our codebase and have to resort to scanf()... - but whatever, the
new code is not much uglier than before, the scanf() actually more
readable (because no macro involved), and it works on all MinGW versions...

parse_hexstring() comes with a unit test, and that still passes, so
"tested well enough" :-) - also compile tested with whatever MinGW
version I have here + GHA.

Your patch has been applied to the master and release/2.7 branch
(long-term compat)

commit 035a88f97b1ffdc88497faeaa0aeb8a72e1eaf4f (master)
commit 326bd05d3db9be075091cd12b7a7c7c798ef9a7e (release/2.7)
Author: Heiko Hund
Date:   Wed Jul 8 20:56:53 2026 +0200

     mingw: avoid C99 hh scanf length modifier

     Signed-off-by: Heiko Hund <heiko@ist.eigentlich.net>
     Acked-by: Frank Lichtenheld <frank@lichtenheld.com>
     Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1733
     Message-Id: <20260708185659.10219-1-gert@greenie.muc.de>
     URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg37544.html
     Signed-off-by: Gert Doering <gert@greenie.muc.de>


--
kind regards,

Gert Doering
  

Patch

diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c
index 3d79fe5..ee43d65 100644
--- a/src/openvpn/crypto.c
+++ b/src/openvpn/crypto.c
@@ -1473,9 +1473,9 @@ 
                     hex_byte[hb_index++] = c;
                     if (hb_index == 2)
                     {
-                        uint8_t u;
-                        ASSERT(sscanf((const char *)hex_byte, "%" SCNx8, &u) == 1);
-                        *out++ = u;
+                        unsigned int u;
+                        ASSERT(sscanf((const char *)hex_byte, "%2x", &u) == 1);
+                        *out++ = (uint8_t)u;
                         hb_index = 0;
                         if (++count == keylen)
                         {
diff --git a/src/openvpn/cryptoapi.c b/src/openvpn/cryptoapi.c
index bf80bbd..0f95ab7 100644
--- a/src/openvpn/cryptoapi.c
+++ b/src/openvpn/cryptoapi.c
@@ -169,10 +169,12 @@ 
             break;
         }
 
-        if (!isxdigit(p[0]) || !isxdigit(p[1]) || sscanf(p, "%2hhx", &arr[i++]) != 1)
+        unsigned int b;
+        if (!isxdigit(p[0]) || !isxdigit(p[1]) || sscanf(p, "%2x", &b) != 1)
         {
             return 0;
         }
+        arr[i++] = (unsigned char)b;
     }
     return i;
 }