Page MenuHome GnuPG

Asan findings in iconv configure test causing config failure
Closed, ResolvedPublic

Description

Hi Everyone,

I'm performing a Asan run on GnuPG 2.2.15 and all of its dependencies. Everything was built with -fsanitize=address -fno-omit-frame-pointer. For Autotools projects the two flags get placed in CFLAGS, CXXFLAGS and LDFLAGS.

GnuPG is failing to configure due to iConvert. It looks like the configure test program is failing to close its open handles, which is causing an Asan findings. Handles like cd_utf8_to_88591 have to be closed.

From config.log:

configure:11684: checking for working iconv
configure:11760: gcc -o conftest -g2 -O2 -fsanitize=address -fno-omit-frame-pointer -march=native -fPIC -pthread  -I/var/sanitize/include -DNDEBUG -L/var/sanitize/lib64 -fsanitize=address -Wl,-R,/var/sanitize/lib64 -Wl,--enable-new-dtags conftest.c  /var/sanitize/lib64/libiconv.so -Wl,-rpath -Wl,/var/sanitize/lib64 >&5
configure:11760: $? = 0
configure:11760: ./conftest

=================================================================
==22607==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 144 byte(s) in 1 object(s) allocated from:
    #0 0x7f76f02be008 in malloc (/lib64/libasan.so.5+0xef008)
    #1 0x7f76efee6f5e in libiconv_open iconv.c:234
    #2 0x400a03 in main /home/build/gnupg-2.2.15/conftest.c:117
    #3 0x7f76ef8e711a in __libc_start_main (/lib64/libc.so.6+0x2311a)

Direct leak of 144 byte(s) in 1 object(s) allocated from:
    #0 0x7f76f02be008 in malloc (/lib64/libasan.so.5+0xef008)
    #1 0x7f76efee6f5e in libiconv_open iconv.c:234
    #2 0x4008ce in main /home/build/gnupg-2.2.15/conftest.c:78
    #3 0x7f76ef8e711a in __libc_start_main (/lib64/libc.so.6+0x2311a)

SUMMARY: AddressSanitizer: 288 byte(s) leaked in 2 allocation(s).
configure:11760: $? = 1
configure: program exited with status 1
configure: failed program was:
| /* confdefs.h */
| #define PACKAGE_NAME "gnupg"
| #define PACKAGE_TARNAME "gnupg"
| #define PACKAGE_VERSION "2.2.15"
| #define PACKAGE_STRING "gnupg 2.2.15"
| #define PACKAGE_BUGREPORT "https://bugs.gnupg.org"
| #define PACKAGE_URL ""
| #define GNUPG_SWDB_TAG "gnupg22"
| #define PACKAGE "gnupg"
| #define VERSION "2.2.15"
| #define STDC_HEADERS 1
| #define HAVE_SYS_TYPES_H 1
| #define HAVE_SYS_STAT_H 1
| #define HAVE_STDLIB_H 1
| #define HAVE_STRING_H 1
| #define HAVE_MEMORY_H 1
| #define HAVE_STRINGS_H 1
| #define HAVE_INTTYPES_H 1
| #define HAVE_STDINT_H 1
| #define HAVE_UNISTD_H 1
| #define __EXTENSIONS__ 1
| #define _ALL_SOURCE 1
| #define _GNU_SOURCE 1
| #define _POSIX_PTHREAD_SEMANTICS 1
| #define _TANDEM_SOURCE 1
| #define PACKAGE "gnupg"
| #define PACKAGE_GT "gnupg2"
| #define VERSION "2.2.15"
| #define PACKAGE_BUGREPORT "https://bugs.gnupg.org"
| #define NEED_LIBGCRYPT_VERSION "1.7.0"
| #define NEED_KSBA_VERSION "1.3.4"
| #define NEED_NTBTLS_VERSION "0.1.0"
| #define SECMEM_BUFFER_SIZE 32768
| #define AGENT_S2K_CALIBRATION 100
| #define USE_LIBDNS 1
| #define GPG_USE_RSA 1
| #define GPG_USE_ECDH 1
| #define GPG_USE_ECDSA 1
| #define GPG_USE_EDDSA 1
| #define GPG_USE_IDEA 1
| #define GPG_USE_CAST5 1
| #define GPG_USE_BLOWFISH 1
| #define GPG_USE_AES128 1
| #define GPG_USE_AES192 1
| #define GPG_USE_AES256 1
| #define GPG_USE_TWOFISH 1
| #define GPG_USE_CAMELLIA128 1
| #define GPG_USE_CAMELLIA192 1
| #define GPG_USE_CAMELLIA256 1
| #define GPG_USE_MD5 1
| #define GPG_USE_RMD160 1
| #define GPG_USE_SHA224 1
| #define GPG_USE_SHA384 1
| #define GPG_USE_SHA512 1
| #define PK_UID_CACHE_SIZE 4096
| #define ENABLE_CARD_SUPPORT 1
| #define USE_DIRMNGR_AUTO_START 1
| #define HAVE_PSELECT_NO_EINTR 1
| #define EXEEXT ""
| #define GNUPG_LIBASSUAN_VERSION "2.5.3"
| #define ENCFS "/usr/bin/encfs"
| #define FUSERMOUNT "/bin/fusermount"
| #define HAVE_LIBUTIL 1
| #define SHRED "/bin/shred"
| #define HAVE_NPTH 1
| #define USE_NPTH 1
| #define HTTP_USE_NTBTLS 1
| #define PRINTABLE_OS_NAME "GNU/Linux"
| /* end confdefs.h.  */
|
| #include <iconv.h>
| #include <string.h>
| int main ()
| {
|   /* Test against AIX 5.1 bug: Failures are not distinguishable from successful
|      returns.  */
|   {
|     iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8");
|     if (cd_utf8_to_88591 != (iconv_t)(-1))
|       {
|         static const char input[] = "\342\202\254"; /* EURO SIGN */
|         char buf[10];
|         const char *inptr = input;
|         size_t inbytesleft = strlen (input);
|         char *outptr = buf;
|         size_t outbytesleft = sizeof (buf);
|         size_t res = iconv (cd_utf8_to_88591,
|                             (char **) &inptr, &inbytesleft,
|                             &outptr, &outbytesleft);
|         if (res == 0)
|           return 1;
|       }
|   }
| #if 0 /* This bug could be worked around by the caller.  */
|   /* Test against HP-UX 11.11 bug: Positive return value instead of 0.  */
|   {
|     iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591");
|     if (cd_88591_to_utf8 != (iconv_t)(-1))
|       {
|         static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
|         char buf[50];
|         const char *inptr = input;
|         size_t inbytesleft = strlen (input);
|         char *outptr = buf;
|         size_t outbytesleft = sizeof (buf);
|         size_t res = iconv (cd_88591_to_utf8,
|                             (char **) &inptr, &inbytesleft,
|                             &outptr, &outbytesleft);
|         if ((int)res > 0)
|           return 1;
|       }
|   }
| #endif
|   /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
|      provided.  */
|   if (/* Try standardized names.  */
|       iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1)
|       /* Try IRIX, OSF/1 names.  */
|       && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1)
|       /* Try AIX names.  */
|       && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1)
|       /* Try HP-UX names.  */
|       && iconv_open ("utf8", "eucJP") == (iconv_t)(-1))
|     return 1;
|   return 0;
| }
configure:11772: result: no

Event Timeline

JW created this object in space S1 Public.

This patch tested OK.

--- m4/iconv.m4
+++ m4/iconv.m4
@@ -68,11 +68,12 @@
 #include <string.h>
 int main ()
 {
+  iconv_t cd;
   /* Test against AIX 5.1 bug: Failures are not distinguishable from successful
      returns.  */
   {
-    iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8");
-    if (cd_utf8_to_88591 != (iconv_t)(-1))
+    cd = iconv_open ("ISO8859-1", "UTF-8");
+    if (cd != (iconv_t)(-1))
       {
         static const char input[] = "\342\202\254"; /* EURO SIGN */
         char buf[10];
@@ -80,9 +81,10 @@
         size_t inbytesleft = strlen (input);
         char *outptr = buf;
         size_t outbytesleft = sizeof (buf);
-        size_t res = iconv (cd_utf8_to_88591,
+        size_t res = iconv (cd,
                             (char **) &inptr, &inbytesleft,
                             &outptr, &outbytesleft);
+        iconv_close(cd);
         if (res == 0)
           return 1;
       }
@@ -90,8 +92,8 @@
 #if 0 /* This bug could be worked around by the caller.  */
   /* Test against HP-UX 11.11 bug: Positive return value instead of 0.  */
   {
-    iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591");
-    if (cd_88591_to_utf8 != (iconv_t)(-1))
+    cd = iconv_open ("utf8", "iso88591");
+    if (cd != (iconv_t)(-1))
       {
         static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
         char buf[50];
@@ -99,9 +101,10 @@
         size_t inbytesleft = strlen (input);
         char *outptr = buf;
         size_t outbytesleft = sizeof (buf);
-        size_t res = iconv (cd_88591_to_utf8,
+        size_t res = iconv (cd,
                             (char **) &inptr, &inbytesleft,
                             &outptr, &outbytesleft);
+        iconv_close(cd);
         if ((int)res > 0)
           return 1;
       }
@@ -110,14 +113,15 @@
   /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
      provided.  */
   if (/* Try standardized names.  */
-      iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1)
+      (cd = iconv_open ("UTF-8", "EUC-JP")) == (iconv_t)(-1)
       /* Try IRIX, OSF/1 names.  */
-      && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1)
+      && (cd = iconv_open ("UTF-8", "eucJP")) == (iconv_t)(-1)
       /* Try AIX names.  */
-      && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1)
+      && (cd = iconv_open ("UTF-8", "IBM-eucJP")) == (iconv_t)(-1)
       /* Try HP-UX names.  */
-      && iconv_open ("utf8", "eucJP") == (iconv_t)(-1))
+      && (cd = iconv_open ("utf8", "eucJP")) == (iconv_t)(-1))
     return 1;
+  iconv_close(cd);
   return 0;
 }], [am_cv_func_iconv_works=yes], [am_cv_func_iconv_works=no],
         [case "$host_os" in
--- configure
+++ configure
@@ -11704,11 +11704,12 @@
 #include <string.h>
 int main ()
 {
+  iconv_t cd;
   /* Test against AIX 5.1 bug: Failures are not distinguishable from successful
      returns.  */
   {
-    iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8");
-    if (cd_utf8_to_88591 != (iconv_t)(-1))
+    cd = iconv_open ("ISO8859-1", "UTF-8");
+    if (cd != (iconv_t)(-1))
       {
         static const char input[] = "\342\202\254"; /* EURO SIGN */
         char buf[10];
@@ -11716,9 +11717,10 @@
         size_t inbytesleft = strlen (input);
         char *outptr = buf;
         size_t outbytesleft = sizeof (buf);
-        size_t res = iconv (cd_utf8_to_88591,
+        size_t res = iconv (cd,
                             (char **) &inptr, &inbytesleft,
                             &outptr, &outbytesleft);
+        iconv_close (cd);
         if (res == 0)
           return 1;
       }
@@ -11726,8 +11728,8 @@
 #if 0 /* This bug could be worked around by the caller.  */
   /* Test against HP-UX 11.11 bug: Positive return value instead of 0.  */
   {
-    iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591");
-    if (cd_88591_to_utf8 != (iconv_t)(-1))
+    cd = iconv_open ("utf8", "iso88591");
+    if (cd != (iconv_t)(-1))
       {
         static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
         char buf[50];
@@ -11735,9 +11737,10 @@
         size_t inbytesleft = strlen (input);
         char *outptr = buf;
         size_t outbytesleft = sizeof (buf);
-        size_t res = iconv (cd_88591_to_utf8,
+        size_t res = iconv (cd,
                             (char **) &inptr, &inbytesleft,
                             &outptr, &outbytesleft);
+        iconv_close (cd);
         if ((int)res > 0)
           return 1;
       }
@@ -11746,14 +11749,15 @@
   /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
      provided.  */
   if (/* Try standardized names.  */
-      iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1)
+      (cd = iconv_open ("UTF-8", "EUC-JP")) == (iconv_t)(-1)
       /* Try IRIX, OSF/1 names.  */
-      && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1)
+      && (cd = iconv_open ("UTF-8", "eucJP")) == (iconv_t)(-1)
       /* Try AIX names.  */
-      && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1)
+      && (cd = iconv_open ("UTF-8", "IBM-eucJP")) == (iconv_t)(-1)
       /* Try HP-UX names.  */
-      && iconv_open ("utf8", "eucJP") == (iconv_t)(-1))
+      && (cd = iconv_open ("utf8", "eucJP")) == (iconv_t)(-1))
     return 1;
+  iconv_close(cd);
   return 0;
 }
 _ACEOF

An FYI... Once we cleared the earlier findings GnuPG tested OK under Asan. GnuPG itself had no findings, and it did not cause any dependent libraries to generate findings.

Another job well done. Congrats.

gniibe triaged this task as Normal priority.
gniibe added a subscriber: gniibe.

Thanks for your report.

I'm going to bring newest m4/iconv.m4 from original (gettext), which apparently fixed file descriptor leaks.

I'm going to bring newest m4/iconv.m4 from original (gettext), which apparently fixed file descriptor leaks.

I think there's a new config.sub and config.guess available, too.

wget -O config.guess 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD'
wget -O config.sub 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD'

We update condig.{guess,sub} only when needed. In the past we had cases with regressions on some rare platforms.