mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-06 15:24:56 +08:00
Improve range checks of options for pg_test_fsync and pg_test_timing
Both tools never had safeguard checks for the options provided, and it was possible to make pg_test_fsync run an infinite amount of time or pass down buggy values to pg_test_timing. These behaviors have existed for a long time, with no actual complaints, so no backpatch is done. Basic TAP tests are introduced for both tools. Author: Michael Paquier Reviewed-by: Peter Eisentraut Discussion: https://postgr.es/m/20200806062759.GE16470@paquier.xyz
This commit is contained in:
parent
41efb83408
commit
4d29e6dbd0
2
src/bin/pg_test_fsync/.gitignore
vendored
2
src/bin/pg_test_fsync/.gitignore
vendored
@ -1 +1,3 @@
|
||||
/pg_test_fsync
|
||||
|
||||
/tmp_check/
|
||||
|
@ -22,6 +22,12 @@ install: all installdirs
|
||||
installdirs:
|
||||
$(MKDIR_P) '$(DESTDIR)$(bindir)'
|
||||
|
||||
check:
|
||||
$(prove_check)
|
||||
|
||||
installcheck:
|
||||
$(prove_installcheck)
|
||||
|
||||
uninstall:
|
||||
rm -f '$(DESTDIR)$(bindir)/pg_test_fsync$(X)'
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "postgres_fe.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <fcntl.h>
|
||||
@ -62,7 +63,7 @@ do { \
|
||||
|
||||
static const char *progname;
|
||||
|
||||
static int secs_per_test = 5;
|
||||
static unsigned int secs_per_test = 5;
|
||||
static int needs_unlink = 0;
|
||||
static char full_buf[DEFAULT_XLOG_SEG_SIZE],
|
||||
*buf,
|
||||
@ -148,6 +149,8 @@ handle_args(int argc, char *argv[])
|
||||
|
||||
int option; /* Command line option */
|
||||
int optindex = 0; /* used by getopt_long */
|
||||
unsigned long optval; /* used for option parsing */
|
||||
char *endptr;
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
@ -173,7 +176,24 @@ handle_args(int argc, char *argv[])
|
||||
break;
|
||||
|
||||
case 's':
|
||||
secs_per_test = atoi(optarg);
|
||||
errno = 0;
|
||||
optval = strtoul(optarg, &endptr, 10);
|
||||
|
||||
if (endptr == optarg || *endptr != '\0' ||
|
||||
errno != 0 || optval != (unsigned int) optval)
|
||||
{
|
||||
pg_log_error("invalid argument for option %s", "--secs-per-test");
|
||||
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
secs_per_test = (unsigned int) optval;
|
||||
if (secs_per_test == 0)
|
||||
{
|
||||
pg_log_error("%s must be in range %u..%u",
|
||||
"--secs-per-test", 1, UINT_MAX);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -193,8 +213,8 @@ handle_args(int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf(ngettext("%d second per test\n",
|
||||
"%d seconds per test\n",
|
||||
printf(ngettext("%u second per test\n",
|
||||
"%u seconds per test\n",
|
||||
secs_per_test),
|
||||
secs_per_test);
|
||||
#if PG_O_DIRECT != 0
|
||||
|
25
src/bin/pg_test_fsync/t/001_basic.pl
Normal file
25
src/bin/pg_test_fsync/t/001_basic.pl
Normal file
@ -0,0 +1,25 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Config;
|
||||
use TestLib;
|
||||
use Test::More tests => 12;
|
||||
|
||||
#########################################
|
||||
# Basic checks
|
||||
|
||||
program_help_ok('pg_test_fsync');
|
||||
program_version_ok('pg_test_fsync');
|
||||
program_options_handling_ok('pg_test_fsync');
|
||||
|
||||
#########################################
|
||||
# Test invalid option combinations
|
||||
|
||||
command_fails_like(
|
||||
[ 'pg_test_fsync', '--secs-per-test', 'a' ],
|
||||
qr/\Qpg_test_fsync: error: invalid argument for option --secs-per-test\E/,
|
||||
'pg_test_fsync: invalid argument for option --secs-per-test');
|
||||
command_fails_like(
|
||||
[ 'pg_test_fsync', '--secs-per-test', '0' ],
|
||||
qr/\Qpg_test_fsync: error: --secs-per-test must be in range 1..4294967295\E/,
|
||||
'pg_test_fsync: --secs-per-test must be in range');
|
2
src/bin/pg_test_timing/.gitignore
vendored
2
src/bin/pg_test_timing/.gitignore
vendored
@ -1 +1,3 @@
|
||||
/pg_test_timing
|
||||
|
||||
/tmp_check/
|
||||
|
@ -22,6 +22,12 @@ install: all installdirs
|
||||
installdirs:
|
||||
$(MKDIR_P) '$(DESTDIR)$(bindir)'
|
||||
|
||||
check:
|
||||
$(prove_check)
|
||||
|
||||
installcheck:
|
||||
$(prove_installcheck)
|
||||
|
||||
uninstall:
|
||||
rm -f '$(DESTDIR)$(bindir)/pg_test_timing$(X)'
|
||||
|
||||
|
@ -6,15 +6,17 @@
|
||||
|
||||
#include "postgres_fe.h"
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "getopt_long.h"
|
||||
#include "portability/instr_time.h"
|
||||
|
||||
static const char *progname;
|
||||
|
||||
static int32 test_duration = 3;
|
||||
static unsigned int test_duration = 3;
|
||||
|
||||
static void handle_args(int argc, char *argv[]);
|
||||
static uint64 test_timing(int32);
|
||||
static uint64 test_timing(unsigned int duration);
|
||||
static void output(uint64 loop_count);
|
||||
|
||||
/* record duration in powers of 2 microseconds */
|
||||
@ -47,6 +49,8 @@ handle_args(int argc, char *argv[])
|
||||
|
||||
int option; /* Command line option */
|
||||
int optindex = 0; /* used by getopt_long */
|
||||
unsigned long optval; /* used for option parsing */
|
||||
char *endptr;
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
@ -68,7 +72,25 @@ handle_args(int argc, char *argv[])
|
||||
switch (option)
|
||||
{
|
||||
case 'd':
|
||||
test_duration = atoi(optarg);
|
||||
errno = 0;
|
||||
optval = strtoul(optarg, &endptr, 10);
|
||||
|
||||
if (endptr == optarg || *endptr != '\0' ||
|
||||
errno != 0 || optval != (unsigned int) optval)
|
||||
{
|
||||
fprintf(stderr, _("%s: invalid argument for option %s\n"),
|
||||
progname, "--duration");
|
||||
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
test_duration = (unsigned int) optval;
|
||||
if (test_duration == 0)
|
||||
{
|
||||
fprintf(stderr, _("%s: %s must be in range %u..%u\n"),
|
||||
progname, "--duration", 1, UINT_MAX);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -89,26 +111,15 @@ handle_args(int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (test_duration > 0)
|
||||
{
|
||||
printf(ngettext("Testing timing overhead for %d second.\n",
|
||||
"Testing timing overhead for %d seconds.\n",
|
||||
test_duration),
|
||||
test_duration);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,
|
||||
_("%s: duration must be a positive integer (duration is \"%d\")\n"),
|
||||
progname, test_duration);
|
||||
fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
|
||||
progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf(ngettext("Testing timing overhead for %u second.\n",
|
||||
"Testing timing overhead for %u seconds.\n",
|
||||
test_duration),
|
||||
test_duration);
|
||||
}
|
||||
|
||||
static uint64
|
||||
test_timing(int32 duration)
|
||||
test_timing(unsigned int duration)
|
||||
{
|
||||
uint64 total_time;
|
||||
int64 time_elapsed = 0;
|
||||
|
25
src/bin/pg_test_timing/t/001_basic.pl
Normal file
25
src/bin/pg_test_timing/t/001_basic.pl
Normal file
@ -0,0 +1,25 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Config;
|
||||
use TestLib;
|
||||
use Test::More tests => 12;
|
||||
|
||||
#########################################
|
||||
# Basic checks
|
||||
|
||||
program_help_ok('pg_test_timing');
|
||||
program_version_ok('pg_test_timing');
|
||||
program_options_handling_ok('pg_test_timing');
|
||||
|
||||
#########################################
|
||||
# Test invalid option combinations
|
||||
|
||||
command_fails_like(
|
||||
[ 'pg_test_timing', '--duration', 'a' ],
|
||||
qr/\Qpg_test_timing: invalid argument for option --duration\E/,
|
||||
'pg_test_timing: invalid argument for option --duration');
|
||||
command_fails_like(
|
||||
[ 'pg_test_timing', '--duration', '0' ],
|
||||
qr/\Qpg_test_timing: --duration must be in range 1..4294967295\E/,
|
||||
'pg_test_timing: --duration must be in range');
|
Loading…
Reference in New Issue
Block a user