Git fork

gettext: avoid using gettext if the locale dir is not present

In cc5e1bf99247 (gettext: avoid initialization if the locale dir is not
present, 2018-04-21) Git was taught to avoid a costly gettext start-up
when there are not even any localized messages to work with.

But we still called `gettext()` and `ngettext()` functions.

Which caused a problem in Git for Windows when the libgettext that is
consumed from the MSYS2 project stopped using a runtime prefix in
https://github.com/msys2/MINGW-packages/pull/10461

Due to that change, we now use an unintialized gettext machinery that
might get auto-initialized _using an unintended locale directory_:
`C:\mingw64\share\locale`.

Let's record the fact when the gettext initialization was skipped, and
skip calling the gettext functions accordingly.

This addresses CVE-2023-25815.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>

+10 -1
+4
gettext.c
··· 109 109 setlocale(LC_CTYPE, "C"); 110 110 } 111 111 112 + int git_gettext_enabled = 0; 113 + 112 114 void git_setup_gettext(void) 113 115 { 114 116 const char *podir = getenv(GIT_TEXT_DOMAIN_DIR_ENVIRONMENT); ··· 129 131 setlocale(LC_TIME, ""); 130 132 init_gettext_charset("git"); 131 133 textdomain("git"); 134 + 135 + git_gettext_enabled = 1; 132 136 133 137 free(p); 134 138 }
+6 -1
gettext.h
··· 31 31 int use_gettext_poison(void); 32 32 33 33 #ifndef NO_GETTEXT 34 + extern int git_gettext_enabled; 34 35 void git_setup_gettext(void); 35 36 int gettext_width(const char *s); 36 37 #else 38 + #define git_gettext_enabled (0) 37 39 static inline void git_setup_gettext(void) 38 40 { 39 41 use_gettext_poison(); /* getenv() reentrancy paranoia */ ··· 48 50 { 49 51 if (!*msgid) 50 52 return ""; 51 - return use_gettext_poison() ? "# GETTEXT POISON #" : gettext(msgid); 53 + return use_gettext_poison() ? "# GETTEXT POISON #" : 54 + !git_gettext_enabled ? msgid : gettext(msgid); 52 55 } 53 56 54 57 static inline FORMAT_PRESERVING(1) FORMAT_PRESERVING(2) ··· 56 59 { 57 60 if (use_gettext_poison()) 58 61 return "# GETTEXT POISON #"; 62 + if (!git_gettext_enabled) 63 + return n == 1 ? msgid : plu; 59 64 return ngettext(msgid, plu, n); 60 65 } 61 66