aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/misc/guc.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2008-07-06 19:48:53 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2008-07-06 19:48:53 +0000
commite3780bce5878713b99a9bfb35adac10e0971bd65 (patch)
tree7b88434a603b735dd7caf168ba3c37d02436f954 /src/backend/utils/misc/guc.c
parentbbfb4a0ab93c18927acb53b7cf37f17dc58d3d39 (diff)
downloadpostgresql-e3780bce5878713b99a9bfb35adac10e0971bd65.tar.gz
postgresql-e3780bce5878713b99a9bfb35adac10e0971bd65.zip
Prevent integer overflows during units conversion when displaying a GUC
variable that has units. Per report from Stefan Kaltenbrunner. Backport to 8.2. I also backported my patch of 2007-06-21 that prevented comparable overflows on the input side, since that now seems to have enough field track record to be back-patched safely. That patch included addition of hints listing the available unit names, which I did not bother to strip out of it --- this will make a little more work for the translators, but they can copy the translation from 8.3, and anyway an untranslated hint is better than no hint.
Diffstat (limited to 'src/backend/utils/misc/guc.c')
-rw-r--r--src/backend/utils/misc/guc.c41
1 files changed, 25 insertions, 16 deletions
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index bca9e3fc384..0a1df8e578d 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.432.2.1 2008/05/26 18:54:36 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.432.2.2 2008/07/06 19:48:53 tgl Exp $
*
*--------------------------------------------------------------------
*/
@@ -5824,10 +5824,18 @@ _ShowOption(struct config_generic * record, bool use_units)
val = (*conf->show_hook) ();
else
{
- char unit[4];
- int result = *conf->variable;
+ /*
+ * Use int64 arithmetic to avoid overflows in units
+ * conversion. If INT64_IS_BUSTED we might overflow
+ * anyway and print bogus answers, but there are few
+ * enough such machines that it doesn't seem worth
+ * trying harder.
+ */
+ int64 result = *conf->variable;
+ const char *unit;
- if (use_units && result > 0 && (record->flags & GUC_UNIT_MEMORY))
+ if (use_units && result > 0 &&
+ (record->flags & GUC_UNIT_MEMORY))
{
switch (record->flags & GUC_UNIT_MEMORY)
{
@@ -5842,19 +5850,20 @@ _ShowOption(struct config_generic * record, bool use_units)
if (result % KB_PER_GB == 0)
{
result /= KB_PER_GB;
- strcpy(unit, "GB");
+ unit = "GB";
}
else if (result % KB_PER_MB == 0)
{
result /= KB_PER_MB;
- strcpy(unit, "MB");
+ unit = "MB";
}
else
{
- strcpy(unit, "kB");
+ unit = "kB";
}
}
- else if (use_units && result > 0 && (record->flags & GUC_UNIT_TIME))
+ else if (use_units && result > 0 &&
+ (record->flags & GUC_UNIT_TIME))
{
switch (record->flags & GUC_UNIT_TIME)
{
@@ -5869,33 +5878,33 @@ _ShowOption(struct config_generic * record, bool use_units)
if (result % MS_PER_D == 0)
{
result /= MS_PER_D;
- strcpy(unit, "d");
+ unit = "d";
}
else if (result % MS_PER_H == 0)
{
result /= MS_PER_H;
- strcpy(unit, "h");
+ unit = "h";
}
else if (result % MS_PER_MIN == 0)
{
result /= MS_PER_MIN;
- strcpy(unit, "min");
+ unit = "min";
}
else if (result % MS_PER_S == 0)
{
result /= MS_PER_S;
- strcpy(unit, "s");
+ unit = "s";
}
else
{
- strcpy(unit, "ms");
+ unit = "ms";
}
}
else
- strcpy(unit, "");
+ unit = "";
- snprintf(buffer, sizeof(buffer), "%d%s",
- (int) result, unit);
+ snprintf(buffer, sizeof(buffer), INT64_FORMAT "%s",
+ result, unit);
val = buffer;
}
}