libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

commit 6339d32c8ab40d11d8e86bf6ad155e4103819ade
parent 6edfa653c048800e24a17f7e8cc2bb42659b8d01
Author: Christian Grothoff <christian@grothoff.org>
Date:   Tue, 30 Jun 2026 18:35:50 +0200

do not die on SIGPIPE

Diffstat:
Msrc/main/extract.c | 130+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Msrc/main/extractor_ipc_gnu.c | 10++++++++++
Msrc/main/extractor_plugin_main.c | 27++++++++++++++++++++++-----
Msrc/main/extractor_print.c | 2+-
4 files changed, 124 insertions(+), 45 deletions(-)

diff --git a/src/main/extract.c b/src/main/extract.c @@ -563,7 +563,6 @@ print_bibtex (void *cls, static void finish_bibtex (const char *fn) { - unsigned int i; ssize_t n; const char *et; char temp[20]; @@ -597,19 +596,23 @@ finish_bibtex (const char *fn) et, temp); } - for (i = 0; NULL != btm[i].bibTexName; i++) + for (unsigned int i = 0; NULL != btm[i].bibTexName; i++) if (NULL != btm[i].value) fprintf (stdout, "\t%s = {%s},\n", btm[i].bibTexName, btm[i].value); - fprintf (stdout, "%s", "}\n\n"); + fprintf (stdout, + "%s", + "}\n\n"); } #ifdef WINDOWS static int -_wchar_to_str (const wchar_t *wstr, char **retstr, UINT cp) +_wchar_to_str (const wchar_t *wstr, + char **retstr, + UINT cp) { char *str; int len, lenc; @@ -617,9 +620,17 @@ _wchar_to_str (const wchar_t *wstr, char **retstr, UINT cp) DWORD error; SetLastError (0); - len = WideCharToMultiByte (cp, 0, wstr, -1, NULL, 0, NULL, (cp == CP_UTF8 || - cp == CP_UTF7) ? - NULL : &lossy); + len = WideCharToMultiByte (cp, + 0, + wstr, + -1, + NULL, + 0, + NULL, + (cp == CP_UTF8 || + cp == CP_UTF7) + ? NULL + : &lossy); error = GetLastError (); if (len <= 0) return -1; @@ -627,9 +638,17 @@ _wchar_to_str (const wchar_t *wstr, char **retstr, UINT cp) str = malloc (sizeof (char) * len); SetLastError (0); - lenc = WideCharToMultiByte (cp, 0, wstr, -1, str, len, NULL, (cp == CP_UTF8 || - cp == CP_UTF7) ? - NULL : &lossy); + lenc = WideCharToMultiByte (cp, + 0, + wstr, + -1, + str, + len, + NULL, + (cp == CP_UTF8 || + cp == CP_UTF7) + ? NULL + : &lossy); error = GetLastError (); if (lenc != len) { @@ -651,12 +670,14 @@ _wchar_to_str (const wchar_t *wstr, char **retstr, UINT cp) * freed with a single call to free (); */ static char ** -_make_continuous_arg_copy (int argc, char *const *argv) +_make_continuous_arg_copy (int argc, + char *const *argv) { size_t argvsize = 0; int i; char **new_argv; char *p; + for (i = 0; i < argc; i++) argvsize += strlen (argv[i]) + 1 + sizeof (char *); new_argv = malloc (argvsize + sizeof (char *)); @@ -687,31 +708,38 @@ _make_continuous_arg_copy (int argc, char *const *argv) * @return 0 on success, -1 on failure */ static int -_get_utf8_args (int argc, char *const *argv, int *u8argc, char ***u8argv) +_get_utf8_args (int argc, + char *const *argv, + int *u8argc, + char ***u8argv) { #ifdef WINDOWS wchar_t *wcmd; wchar_t **wargv; int wargc; - int i; char **split_u8argv; wcmd = GetCommandLineW (); if (NULL == wcmd) return -1; - wargv = CommandLineToArgvW (wcmd, &wargc); + wargv = CommandLineToArgvW (wcmd, + &wargc); if (NULL == wargv) return -1; split_u8argv = malloc (wargc * sizeof (char *)); - - for (i = 0; i < wargc; i++) + if (NULL == split_u8argv) + return -1; + for (unsigned int i = 0; i < wargc; i++) { - if (_wchar_to_str (wargv[i], &split_u8argv[i], CP_UTF8) != 0) + if (0 != + _wchar_to_str (wargv[i], + &split_u8argv[i], + CP_UTF8)) { - int j; int e = errno; - for (j = 0; j < i; j++) + + for (unsigned int j = 0; j < i; j++) free (split_u8argv[j]); free (split_u8argv); LocalFree (wargv); @@ -720,7 +748,8 @@ _get_utf8_args (int argc, char *const *argv, int *u8argc, char ***u8argv) } } - *u8argv = _make_continuous_arg_copy (wargc, split_u8argv); + *u8argv = _make_continuous_arg_copy (wargc, + split_u8argv); if (NULL == *u8argv) { free (split_u8argv); @@ -728,11 +757,12 @@ _get_utf8_args (int argc, char *const *argv, int *u8argc, char ***u8argv) } *u8argc = wargc; - for (i = 0; i < wargc; i++) + for (unsigned int i = 0; i < wargc; i++) free (split_u8argv[i]); free (split_u8argv); #else - *u8argv = _make_continuous_arg_copy (argc, argv); + *u8argv = _make_continuous_arg_copy (argc, + argv); if (NULL == *u8argv) return -1; *u8argc = argc; @@ -750,7 +780,8 @@ _get_utf8_args (int argc, char *const *argv, int *u8argc, char ***u8argv) * @return 0 on success */ int -main (int argc, char *argv[]) +main (int argc, + char *argv[]) { unsigned int i; struct EXTRACTOR_PluginList *plugins; @@ -783,9 +814,12 @@ main (int argc, char *argv[]) for (i = 0; i < EXTRACTOR_metatype_get_max (); i++) print[i] = YES; /* default: print everything */ - if (0 != _get_utf8_args (argc, argv, &utf8_argc, &utf8_argv)) + if (0 != _get_utf8_args (argc, argv, + &utf8_argc, &utf8_argv)) { - fprintf (stderr, "Failed to get arguments: %s\n", strerror (errno)); + fprintf (stderr, + "Failed to get arguments: %s\n", + strerror (errno)); return 1; } @@ -824,7 +858,8 @@ main (int argc, char *argv[]) fprintf (stderr, "%s", _ ( - "Illegal combination of options, cannot combine multiple styles of printing.\n")); + "Illegal combination of options, cannot combine multiple styles of printing.\n")) + ; free (utf8_argv); return 0; } @@ -837,7 +872,8 @@ main (int argc, char *argv[]) fprintf (stderr, "%s", _ ( - "Illegal combination of options, cannot combine multiple styles of printing.\n")); + "Illegal combination of options, cannot combine multiple styles of printing.\n")) + ; free (utf8_argv); return 0; } @@ -977,16 +1013,20 @@ main (int argc, char *argv[]) : EXTRACTOR_OPTION_DEFAULT_POLICY); if (NULL == processor) processor = &print_selected_keywords; - + if (NULL == utf8_argv[optind]) + goto cleanup; /* extract keywords */ if (YES == bibtex) fprintf (stdout, - "%s", _ ("% BiBTeX file\n")); - for (i = optind; i < utf8_argc; i++) + "%s", + _ ("% BiBTeX file\n")); + for (i = optind; NULL != utf8_argv[i]; i++) { errno = 0; if (YES == grepfriendly) - fprintf (stdout, "%s ", utf8_argv[i]); + fprintf (stdout, + "%s ", + utf8_argv[i]); else if (NO == bibtex) fprintf (stdout, _ ("Keywords for file %s:\n"), @@ -1003,15 +1043,19 @@ main (int argc, char *argv[]) { struct stat sb; unsigned char *data = NULL; - int f = open (utf8_argv[i], O_RDONLY + int f = open (utf8_argv[i], + O_RDONLY #if WINDOWS | O_BINARY #endif ); if ( (-1 != f) && - (0 == fstat (f, &sb)) && + (0 == fstat (f, + &sb)) && (NULL != (data = malloc ((size_t) sb.st_size))) && - (sb.st_size == read (f, data, (size_t) sb.st_size) ) ) + (sb.st_size == read (f, + data, + (size_t) sb.st_size) ) ) { EXTRACTOR_extract (plugins, NULL, @@ -1024,7 +1068,9 @@ main (int argc, char *argv[]) if (verbose > 0) fprintf (stderr, "%s: %s: %s\n", - utf8_argv[0], utf8_argv[i], strerror (errno)); + utf8_argv[0], + utf8_argv[i], + strerror (errno)); ret = 1; } if (NULL != data) @@ -1033,15 +1079,21 @@ main (int argc, char *argv[]) (void) close (f); } if (YES == grepfriendly) - fprintf (stdout, "%s", "\n"); + fprintf (stdout, + "%s", "\n"); continue; } if (YES == grepfriendly) - fprintf (stdout, "%s", "\n"); + fprintf (stdout, + "%s", + "\n"); if (bibtex) - finish_bibtex (utf8_argv[i]); + finish_bibtex (utf8_argv[optind]); if (verbose > 0) - fprintf (stdout, "%s", "\n"); + fprintf (stdout, + "%s", + "\n"); +cleanup: free (print); free (utf8_argv); EXTRACTOR_plugin_remove_all (plugins); diff --git a/src/main/extractor_ipc_gnu.c b/src/main/extractor_ipc_gnu.c @@ -286,7 +286,17 @@ EXTRACTOR_IPC_channel_create_ (struct EXTRACTOR_PluginList *plugin, pid_t pid; struct InitMessage *init; size_t slen; + static int sigpipe_ignored; + if (! sigpipe_ignored) + { + /* The cpipe_in end may be written to after the plugin child + has died; without ignoring SIGPIPE this would terminate the + host application. As the channel uses pipes (not sockets), + MSG_NOSIGNAL is not applicable, so we ignore SIGPIPE here. */ + signal (SIGPIPE, SIG_IGN); + sigpipe_ignored = 1; + } if (NULL == (channel = malloc (sizeof (struct EXTRACTOR_Channel)))) { LOG_STRERROR ("malloc"); diff --git a/src/main/extractor_plugin_main.c b/src/main/extractor_plugin_main.c @@ -682,16 +682,27 @@ read_plugin_data (int fd) memset (ret, 0, sizeof (struct EXTRACTOR_PluginList)); /*GetSystemInfo (&si); ret->allocation_granularity = si.dwAllocationGranularity;*/ - EXTRACTOR_read_all_ (fd, &i, sizeof (size_t)); - if (NULL == (ret->libname = malloc (i))) + if (-1 == EXTRACTOR_read_all_ (fd, &i, sizeof (size_t))) + { + free (ret); + return NULL; + } + if ( (0 == i) || + (NULL == (ret->libname = malloc (i))) ) { free (ret); return NULL; } EXTRACTOR_read_all_ (fd, ret->libname, i); ret->libname[i - 1] = '\0'; - EXTRACTOR_read_all_ (fd, &i, sizeof (size_t)); - if (NULL == (ret->short_libname = malloc (i))) + if (-1 == EXTRACTOR_read_all_ (fd, &i, sizeof (size_t))) + { + free (ret->libname); + free (ret); + return NULL; + } + if ( (0 == i) || + (NULL == (ret->short_libname = malloc (i))) ) { free (ret->libname); free (ret); @@ -699,7 +710,13 @@ read_plugin_data (int fd) } EXTRACTOR_read_all_ (fd, ret->short_libname, i); ret->short_libname[i - 1] = '\0'; - EXTRACTOR_read_all_ (fd, &i, sizeof (size_t)); + if (-1 == EXTRACTOR_read_all_ (fd, &i, sizeof (size_t))) + { + free (ret->short_libname); + free (ret->libname); + free (ret); + return NULL; + } if (0 == i) { ret->plugin_options = NULL; diff --git a/src/main/extractor_print.c b/src/main/extractor_print.c @@ -63,6 +63,7 @@ EXTRACTOR_meta_data_print (void *handle, if (EXTRACTOR_METAFORMAT_UTF8 != format) return 0; + mt = EXTRACTOR_metatype_to_string (type); #if HAVE_ICONV cd = iconv_open (nl_langinfo (CODESET), "UTF-8"); @@ -79,7 +80,6 @@ EXTRACTOR_meta_data_print (void *handle, } else { - mt = EXTRACTOR_metatype_to_string (type); ret = fprintf (handle, "%s - %s\n", (NULL == mt)