diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
index 1e6f254c2ca0bb61961eb5c615c2b3dc84d91402..cde9eb2e1adbed8f90f7d16ea0514cd14c37b445 100644
--- a/src/bin/psql/print.c
+++ b/src/bin/psql/print.c
@@ -2524,16 +2524,24 @@ setDecimalLocale(void)
 
 	extlconv = localeconv();
 
+	/* Don't accept an empty decimal_point string */
 	if (*extlconv->decimal_point)
 		decimal_point = pg_strdup(extlconv->decimal_point);
 	else
 		decimal_point = ".";	/* SQL output standard */
 
-	if (*extlconv->grouping && atoi(extlconv->grouping) > 0)
-		groupdigits = atoi(extlconv->grouping);
-	else
+	/*
+	 * Although the Open Group standard allows locales to supply more than one
+	 * group width, we consider only the first one, and we ignore any attempt
+	 * to suppress grouping by specifying CHAR_MAX.  As in the backend's
+	 * cash.c, we must apply a range check to avoid being fooled by variant
+	 * CHAR_MAX values.
+	 */
+	groupdigits = *extlconv->grouping;
+	if (groupdigits <= 0 || groupdigits > 6)
 		groupdigits = 3;		/* most common */
 
+	/* Don't accept an empty thousands_sep string, either */
 	/* similar code exists in formatting.c */
 	if (*extlconv->thousands_sep)
 		thousands_sep = pg_strdup(extlconv->thousands_sep);