Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitce17de5

Browse files
committed
Reject non-ASCII locale names.
Commitbf03cfd started scanning all available BCP 47 locale names onWindows. This caused an abort/crash in the Windows runtime library ifthe default locale name contained non-ASCII characters, because of ouruse of the setlocale() save/restore pattern with "char" strings. Afterswitching to another locale with a different encoding, the saved namecould no longer be understood, and setlocale() would abort."Turkish_Türkiye.1254" is the example from recent reports, but there areother examples of countries and languages with non-ASCII characters intheir names, and they appear in Windows' (old style) locale names.To defend against this:1. In initdb, reject non-ASCII locale names given explicity on thecommand line, or returned by the operating system environment withsetlocale(..., ""), or "canonicalized" by the operating system when weset it.2. In initdb only, perform the save-and-restore with Windows'non-standard wchar_t variant of setlocale(), so that it is not subjectto round trip failures stemming from char string encoding confusion.3. In the backend, we don't have to worry about the save-and-restoreproblem because we have already vetted the defaults, so we just have tomake sure that CREATE DATABASE also rejects non-ASCII names in any newdatabases. SET lc_XXX doesn't suffer from the problem, but the banapplies to it too because it uses check_locale(). CREATE COLLATIONdoesn't suffer from the problem either, but it doesn't usecheck_locale() so it is not included in the new ban for now, to minimizethe change.Anyone who encounters the new error message should either create a newduplicated locale with an ASCII-only name using Windows Locale Builder,or consider using BCP 47 names like "tr-TR". Users already couldn'tinitialize a cluster with "Turkish_Türkiye.1254" on PostgreSQL 16+, butthe new failure mode is an error message that explains why, instead of acrash.Back-patch to 16, wherebf03cfd landed. Older versions are affectedin theory too, but only 16 and later are causing crash reports.Reviewed-by: Andrew Dunstan <andrew@dunslane.net> (the idea, not the patch)Reported-by: Haifang Wang (Centific Technologies Inc) <v-haiwang@microsoft.com>Discussion:https://postgr.es/m/PH8PR21MB3902F334A3174C54058F792CE5182%40PH8PR21MB3902.namprd21.prod.outlook.com
1 parent65f431a commitce17de5

File tree

2 files changed

+93
-17
lines changed

2 files changed

+93
-17
lines changed

‎src/backend/utils/adt/pg_locale.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#include"access/htup_details.h"
5858
#include"catalog/pg_collation.h"
5959
#include"catalog/pg_control.h"
60+
#include"common/string.h"
6061
#include"mb/pg_wchar.h"
6162
#include"miscadmin.h"
6263
#include"utils/builtins.h"
@@ -281,6 +282,16 @@ check_locale(int category, const char *locale, char **canonname)
281282
char*save;
282283
char*res;
283284

285+
/* Don't let Windows' non-ASCII locale names in. */
286+
if (!pg_is_ascii(locale))
287+
{
288+
ereport(WARNING,
289+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
290+
errmsg("locale name \"%s\" contains non-ASCII characters",
291+
locale)));
292+
return false;
293+
}
294+
284295
if (canonname)
285296
*canonname=NULL;/* in case of failure */
286297

@@ -303,6 +314,18 @@ check_locale(int category, const char *locale, char **canonname)
303314
elog(WARNING,"failed to restore old locale \"%s\"",save);
304315
pfree(save);
305316

317+
/* Don't let Windows' non-ASCII locale names out. */
318+
if (canonname&&*canonname&& !pg_is_ascii(*canonname))
319+
{
320+
ereport(WARNING,
321+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
322+
errmsg("locale name \"%s\" contains non-ASCII characters",
323+
*canonname)));
324+
pfree(*canonname);
325+
*canonname=NULL;
326+
return false;
327+
}
328+
306329
return (res!=NULL);
307330
}
308331

‎src/bin/initdb/initdb.c

Lines changed: 70 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,61 @@ do { \
336336
output_failed = true, output_errno = errno; \
337337
} while (0)
338338

339+
#ifdefWIN32
340+
typedefwchar_t*save_locale_t;
341+
#else
342+
typedefchar*save_locale_t;
343+
#endif
344+
345+
/*
346+
* Save a copy of the current global locale's name, for the given category.
347+
* The returned value must be passed to restore_global_locale().
348+
*
349+
* Since names from the environment haven't been vetted for non-ASCII
350+
* characters, we use the wchar_t variant of setlocale() on Windows. Otherwise
351+
* they might not survive a save-restore round trip: when restoring, the name
352+
* itself might be interpreted with a different encoding by plain setlocale(),
353+
* after we switch to another locale in between. (This is a problem only in
354+
* initdb, not in similar backend code where the global locale's name should
355+
* already have been verified as ASCII-only.)
356+
*/
357+
staticsave_locale_t
358+
save_global_locale(intcategory)
359+
{
360+
save_locale_tsave;
361+
362+
#ifdefWIN32
363+
save=_wsetlocale(category,NULL);
364+
if (!save)
365+
pg_fatal("_wsetlocale() failed");
366+
save=wcsdup(save);
367+
if (!save)
368+
pg_fatal("out of memory");
369+
#else
370+
save=setlocale(category,NULL);
371+
if (!save)
372+
pg_fatal("setlocale() failed");
373+
save=pg_strdup(save);
374+
#endif
375+
returnsave;
376+
}
377+
378+
/*
379+
* Restore the global locale returned by save_global_locale().
380+
*/
381+
staticvoid
382+
restore_global_locale(intcategory,save_locale_tsave)
383+
{
384+
#ifdefWIN32
385+
if (!_wsetlocale(category,save))
386+
pg_fatal("failed to restore old locale");
387+
#else
388+
if (!setlocale(category,save))
389+
pg_fatal("failed to restore old locale \"%s\"",save);
390+
#endif
391+
free(save);
392+
}
393+
339394
/*
340395
* Escape single quotes and backslashes, suitably for insertions into
341396
* configuration files or SQL E'' strings.
@@ -2065,16 +2120,13 @@ locale_date_order(const char *locale)
20652120
char*posD;
20662121
char*posM;
20672122
char*posY;
2068-
char*save;
2123+
save_locale_tsave;
20692124
size_tres;
20702125
intresult;
20712126

20722127
result=DATEORDER_MDY;/* default */
20732128

2074-
save=setlocale(LC_TIME,NULL);
2075-
if (!save)
2076-
returnresult;
2077-
save=pg_strdup(save);
2129+
save=save_global_locale(LC_TIME);
20782130

20792131
setlocale(LC_TIME,locale);
20802132

@@ -2085,8 +2137,7 @@ locale_date_order(const char *locale)
20852137

20862138
res=my_strftime(buf,sizeof(buf),"%x",&testtime);
20872139

2088-
setlocale(LC_TIME,save);
2089-
free(save);
2140+
restore_global_locale(LC_TIME,save);
20902141

20912142
if (res==0)
20922143
returnresult;
@@ -2123,18 +2174,17 @@ locale_date_order(const char *locale)
21232174
staticvoid
21242175
check_locale_name(intcategory,constchar*locale,char**canonname)
21252176
{
2126-
char*save;
2177+
save_locale_tsave;
21272178
char*res;
21282179

2180+
/* Don't let Windows' non-ASCII locale names in. */
2181+
if (locale&& !pg_is_ascii(locale))
2182+
pg_fatal("locale name \"%s\" contains non-ASCII characters",locale);
2183+
21292184
if (canonname)
21302185
*canonname=NULL;/* in case of failure */
21312186

2132-
save=setlocale(category,NULL);
2133-
if (!save)
2134-
pg_fatal("setlocale() failed");
2135-
2136-
/* save may be pointing at a modifiable scratch variable, so copy it. */
2137-
save=pg_strdup(save);
2187+
save=save_global_locale(category);
21382188

21392189
/* for setlocale() call */
21402190
if (!locale)
@@ -2148,9 +2198,7 @@ check_locale_name(int category, const char *locale, char **canonname)
21482198
*canonname=pg_strdup(res);
21492199

21502200
/* restore old value. */
2151-
if (!setlocale(category,save))
2152-
pg_fatal("failed to restore old locale \"%s\"",save);
2153-
free(save);
2201+
restore_global_locale(category,save);
21542202

21552203
/* complain if locale wasn't valid */
21562204
if (res==NULL)
@@ -2174,6 +2222,11 @@ check_locale_name(int category, const char *locale, char **canonname)
21742222
pg_fatal("invalid locale settings; check LANG and LC_* environment variables");
21752223
}
21762224
}
2225+
2226+
/* Don't let Windows' non-ASCII locale names out. */
2227+
if (canonname&& !pg_is_ascii(*canonname))
2228+
pg_fatal("locale name \"%s\" contains non-ASCII characters",
2229+
*canonname);
21772230
}
21782231

21792232
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp