Re: [HACKERS] Strange interval arithmetic - Mailing list pgsql-patches
From | Bruce Momjian |
---|---|
Subject | Re: [HACKERS] Strange interval arithmetic |
Date | |
Msg-id | 200512012037.jB1KbMo23338@candle.pha.pa.us Whole thread Raw |
Responses |
Re: [HACKERS] Strange interval arithmetic
|
List | pgsql-patches |
I started working on this problem on Tuesday, but was in New York City yesterday so I was not able to comment on this patch before. I think the one applied is great. (I added C comments on the use of "errno = 0". Here is the patch I was working on. It does us a separate libpq strtol() function, but I question whether it is worth it, or if it is meaningful when used by FRONTEND applications. Anyway, I am just throwing it out if it gives others ideas. --------------------------------------------------------------------------- Michael Fuhr wrote: > On Wed, Nov 30, 2005 at 02:01:46PM -0500, Tom Lane wrote: > > Michael Fuhr <mike@fuhr.org> writes: > > > Any preferences on an approach? The simplest and easiest to verify > > > would be to raise an error for just this particular case; a TODO > > > item might be to change how the string is parsed to allow values > > > larger than LONG_MAX. > > > > I think the latter would be a feature enhancement and therefore not > > good material to back-patch. Just erroring out seems appropriate > > for now. > > Agreed. I'm thinking about rewriting strtol() calls in datetime.c > to look like this: > > errno = 0; > val = strtol(field[i], &cp, 10); > if (errno == ERANGE) > return DTERR_FIELD_OVERFLOW; > > Does that look okay? Or would you rather raise an error with ereport()? > > > > I see several calls to strtol() that aren't checked for overflow but > > > that might not be relevant to this problem, so I'm thinking this patch > > > ought not touch them. Maybe that's another TODO item. > > > > If it's possible for them to be given overflowing input, they probably > > ought to be checked. > > I'm looking at all the strtol() calls in datetime.c right now; I > haven't looked anywhere else yet. Should I bother checking values > that will be range checked later anyway? Time zone displacements, > for example? > > -- > Michael Fuhr > > ---------------------------(end of broadcast)--------------------------- > TIP 1: if posting/reading through Usenet, please send an appropriate > subscribe-nomail command to majordomo@postgresql.org so that your > message can get through to the mailing list cleanly > -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073 Index: src/backend/libpq/ip.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/libpq/ip.c,v retrieving revision 1.33 diff -c -c -r1.33 ip.c *** src/backend/libpq/ip.c 22 Nov 2005 18:17:11 -0000 1.33 --- src/backend/libpq/ip.c 1 Dec 2005 18:40:02 -0000 *************** *** 342,348 **** long bits; char *endptr; ! bits = strtol(numbits, &endptr, 10); if (*numbits == '\0' || *endptr != '\0') return -1; --- 342,348 ---- long bits; char *endptr; ! bits = pg_strtol_range(numbits, &endptr, 10); if (*numbits == '\0' || *endptr != '\0') return -1; Index: src/backend/utils/adt/datetime.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v retrieving revision 1.161 diff -c -c -r1.161 datetime.c *** src/backend/utils/adt/datetime.c 22 Nov 2005 18:17:22 -0000 1.161 --- src/backend/utils/adt/datetime.c 1 Dec 2005 18:40:03 -0000 *************** *** 1013,1019 **** if (tzp == NULL) return DTERR_BAD_FORMAT; ! val = strtol(field[i], &cp, 10); j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday); /* Get the time zone from the end of the string */ --- 1013,1019 ---- if (tzp == NULL) return DTERR_BAD_FORMAT; ! val = pg_strtol_range(field[i], &cp, 10); j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday); /* Get the time zone from the end of the string */ *************** *** 1158,1164 **** char *cp; int val; ! val = strtol(field[i], &cp, 10); /* * only a few kinds are allowed to have an embedded --- 1158,1164 ---- char *cp; int val; ! val = pg_strtol_range(field[i], &cp, 10); /* * only a few kinds are allowed to have an embedded *************** *** 1915,1921 **** break; } ! val = strtol(field[i], &cp, 10); /* * only a few kinds are allowed to have an embedded --- 1915,1921 ---- break; } ! val = pg_strtol_range(field[i], &cp, 10); /* * only a few kinds are allowed to have an embedded *************** *** 2456,2466 **** *tmask = DTK_TIME_M; ! tm->tm_hour = strtol(str, &cp, 10); if (*cp != ':') return DTERR_BAD_FORMAT; str = cp + 1; ! tm->tm_min = strtol(str, &cp, 10); if (*cp == '\0') { tm->tm_sec = 0; --- 2456,2466 ---- *tmask = DTK_TIME_M; ! tm->tm_hour = pg_strtol_range(str, &cp, 10); if (*cp != ':') return DTERR_BAD_FORMAT; str = cp + 1; ! tm->tm_min = pg_strtol_range(str, &cp, 10); if (*cp == '\0') { tm->tm_sec = 0; *************** *** 2471,2477 **** else { str = cp + 1; ! tm->tm_sec = strtol(str, &cp, 10); if (*cp == '\0') *fsec = 0; else if (*cp == '.') --- 2471,2477 ---- else { str = cp + 1; ! tm->tm_sec = pg_strtol_range(str, &cp, 10); if (*cp == '\0') *fsec = 0; else if (*cp == '.') *************** *** 2522,2528 **** *tmask = 0; ! val = strtol(str, &cp, 10); if (cp == str) return DTERR_BAD_FORMAT; --- 2522,2528 ---- *tmask = 0; ! val = pg_strtol_range(str, &cp, 10); if (cp == str) return DTERR_BAD_FORMAT; *************** *** 2809,2819 **** if (*str != '+' && *str != '-') return DTERR_BAD_FORMAT; ! hr = strtol(str + 1, &cp, 10); /* explicit delimiter? */ if (*cp == ':') ! min = strtol(cp + 1, &cp, 10); /* otherwise, might have run things together... */ else if (*cp == '\0' && strlen(str) > 3) { --- 2809,2819 ---- if (*str != '+' && *str != '-') return DTERR_BAD_FORMAT; ! hr = pg_strtol_range(str + 1, &cp, 10); /* explicit delimiter? */ if (*cp == ':') ! min = pg_strtol_range(cp + 1, &cp, 10); /* otherwise, might have run things together... */ else if (*cp == '\0' && strlen(str) > 3) { *************** *** 3056,3062 **** case DTK_DATE: case DTK_NUMBER: ! val = strtol(field[i], &cp, 10); if (type == IGNORE_DTF) type = DTK_SECOND; --- 3056,3062 ---- case DTK_DATE: case DTK_NUMBER: ! val = pg_strtol_range(field[i], &cp, 10); if (type == IGNORE_DTF) type = DTK_SECOND; Index: src/backend/utils/adt/numeric.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v retrieving revision 1.88 diff -c -c -r1.88 numeric.c *** src/backend/utils/adt/numeric.c 22 Nov 2005 18:17:23 -0000 1.88 --- src/backend/utils/adt/numeric.c 1 Dec 2005 18:40:08 -0000 *************** *** 2812,2818 **** char *endptr; cp++; ! exponent = strtol(cp, &endptr, 10); if (endptr == cp) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), --- 2812,2818 ---- char *endptr; cp++; ! exponent = pg_strtol_range(cp, &endptr, 10); if (endptr == cp) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), Index: src/include/port.h =================================================================== RCS file: /cvsroot/pgsql/src/include/port.h,v retrieving revision 1.84 diff -c -c -r1.84 port.h *** src/include/port.h 15 Oct 2005 02:49:41 -0000 1.84 --- src/include/port.h 1 Dec 2005 18:40:09 -0000 *************** *** 249,254 **** --- 249,257 ---- #define closesocket close #endif /* WIN32 */ + /* do strtol(), but error out on ERANGE */ + long pg_strtol_range(const char *nptr, char **endptr, int base); + /* * Default "extern" declarations or macro substitutes for library routines. * When necessary, these routines are provided by files in src/port/. Index: src/interfaces/ecpg/pgtypeslib/numeric.c =================================================================== RCS file: /cvsroot/pgsql/src/interfaces/ecpg/pgtypeslib/numeric.c,v retrieving revision 1.24 diff -c -c -r1.24 numeric.c *** src/interfaces/ecpg/pgtypeslib/numeric.c 22 Nov 2005 18:17:32 -0000 1.24 --- src/interfaces/ecpg/pgtypeslib/numeric.c 1 Dec 2005 18:40:11 -0000 *************** *** 218,224 **** char *endptr; (*ptr)++; ! exponent = strtol(*ptr, &endptr, 10); if (endptr == (*ptr)) { errno = PGTYPES_NUM_BAD_NUMERIC; --- 218,224 ---- char *endptr; (*ptr)++; ! exponent = pg_strtol_range(*ptr, &endptr, 10); if (endptr == (*ptr)) { errno = PGTYPES_NUM_BAD_NUMERIC; Index: src/port/exec.c =================================================================== RCS file: /cvsroot/pgsql/src/port/exec.c,v retrieving revision 1.40 diff -c -c -r1.40 exec.c *** src/port/exec.c 22 Nov 2005 18:17:34 -0000 1.40 --- src/port/exec.c 1 Dec 2005 18:40:11 -0000 *************** *** 592,594 **** --- 592,618 ---- return -1; } + + + /* + * This really should be in its own file, but it so small, it hardly + * seems worth it. + */ + long + pg_strtol_range(const char *nptr, char **endptr, int base) + { + long ret = strtol(nptr, endptr, base); + + if (errno == ERANGE) + { + #ifndef FRONTEND + elog(ERROR, _("value not in supported range for an integer: \"%s\""), nptr); + #else + /* Keep strings identical for ease of translation */ + fprintf(stderr, _("value not in supported range for an integer: \"%s\""), nptr); + fputc('\n', stderr); + #endif + return LONG_MAX; + } + return ret; + }
pgsql-patches by date: