diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2008-07-06 19:48:53 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2008-07-06 19:48:53 +0000 |
commit | e3780bce5878713b99a9bfb35adac10e0971bd65 (patch) | |
tree | 7b88434a603b735dd7caf168ba3c37d02436f954 | |
parent | bbfb4a0ab93c18927acb53b7cf37f17dc58d3d39 (diff) | |
download | postgresql-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.
-rw-r--r-- | src/backend/utils/misc/guc.c | 41 |
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; } } |