Thread

Commits

  1. Make [U]INT64CONST safe for use in #if conditions.

  2. Ensure SIZE_MAX can be used throughout our code.

  3. Teach libpq to detect integer overflow in the row count of a PGresult.

  1. Missing SIZE_MAX

    Tom Lane <tgl@sss.pgh.pa.us> — 2017-09-01T15:09:55Z

    Commit 2e70d6b5e added a dependency on SIZE_MAX to libpq/fe_exec.c.
    According to C99 and recent POSIX, that symbol should be provided
    by <stdint.h>, but SUS v2 (POSIX 2001) doesn't require <stdint.h>
    to exist at all ... and I now notice that gaur/pademelon doesn't
    have it, and unsurprisingly is failing to compile fe_exec.c.
    
    We have a workaround for that symbol in timezone/private.h:
    
    #ifndef SIZE_MAX
    #define SIZE_MAX ((size_t) -1)
    #endif
    
    and a bit of grepping finds other places that are using the (size_t) -1
    trick explicitly.  So what I'm tempted to do is move the above stanza
    into c.h.  Any objections?
    
    			regards, tom lane
    
    
    
  2. Re: Missing SIZE_MAX

    Robert Haas <robertmhaas@gmail.com> — 2017-09-01T15:48:46Z

    On Fri, Sep 1, 2017 at 11:09 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
    > Commit 2e70d6b5e added a dependency on SIZE_MAX to libpq/fe_exec.c.
    > According to C99 and recent POSIX, that symbol should be provided
    > by <stdint.h>, but SUS v2 (POSIX 2001) doesn't require <stdint.h>
    > to exist at all ... and I now notice that gaur/pademelon doesn't
    > have it, and unsurprisingly is failing to compile fe_exec.c.
    >
    > We have a workaround for that symbol in timezone/private.h:
    >
    > #ifndef SIZE_MAX
    > #define SIZE_MAX ((size_t) -1)
    > #endif
    >
    > and a bit of grepping finds other places that are using the (size_t) -1
    > trick explicitly.  So what I'm tempted to do is move the above stanza
    > into c.h.  Any objections?
    
    Not from me.
    
    -- 
    Robert Haas
    EnterpriseDB: http://www.enterprisedb.com
    The Enterprise PostgreSQL Company
    
    
    
  3. Re: Missing SIZE_MAX

    Alvaro Herrera <alvherre@alvh.no-ip.org> — 2017-09-01T15:50:47Z

    Tom Lane wrote:
    
    > We have a workaround for that symbol in timezone/private.h:
    > 
    > #ifndef SIZE_MAX
    > #define SIZE_MAX ((size_t) -1)
    > #endif
    > 
    > and a bit of grepping finds other places that are using the (size_t) -1
    > trick explicitly.  So what I'm tempted to do is move the above stanza
    > into c.h.
    
    Sounds good to me.
    
    -- 
    Álvaro Herrera                https://www.2ndQuadrant.com/
    PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
    
    
    
  4. Re: Missing SIZE_MAX

    Tom Lane <tgl@sss.pgh.pa.us> — 2017-09-01T16:22:21Z

    [ warning: more than you really wanted to know ahead ]
    
    Alvaro Herrera <alvherre@alvh.no-ip.org> writes:
    > Tom Lane wrote:
    >> We have a workaround for that symbol in timezone/private.h:
    >> #ifndef SIZE_MAX
    >> #define SIZE_MAX ((size_t) -1)
    >> #endif
    >> and a bit of grepping finds other places that are using the (size_t) -1
    >> trick explicitly.  So what I'm tempted to do is move the above stanza
    >> into c.h.
    
    > Sounds good to me.
    
    On closer inspection, C99 requires SIZE_MAX and related macros to be a
    "constant expression suitable for use in #if preprocessing directives",
    which we need for the fe-exec.c usage because it does
    
    #if INT_MAX >= (SIZE_MAX / 2)
    		if (newSize > SIZE_MAX / sizeof(PGresAttValue *))
    
    (We could maybe dispense with this #if check, but I feared that doing
    so would result in nanny-ish "expression is constant false" warnings
    from some compilers on 64-bit platforms.)
    
    Now, that cast doesn't really work in an #if expression.  Some language
    lawyering leads me to conclude that in #if, a C compiler will interpret
    the above value of SIZE_MAX as "((0) -1)", or just signed -1.  So
    fe-exec.c's test will surely evaluate to true, which seems like a safe
    outcome.  But you could certainly imagine other cases where you get
    incorrect results if SIZE_MAX looks like a signed -1 to an #if-test.
    
    When I look into /usr/include/stdint.h on my Linux box, I find
    
    # if __WORDSIZE == 64
    #  define SIZE_MAX		(18446744073709551615UL)
    # else
    #  define SIZE_MAX		(4294967295U)
    # endif
    
    so I thought about trying to duplicate that logic.  We can certainly test
    SIZEOF_SIZE_T == 8 as a substitute for the #if condition.  The hard part
    is arriving at a portable spelling of "UL", since it would need to be
    "ULL" instead on some platforms.  We can't make use of our UINT64CONST
    macro because that includes a cast.  So it seems like if we want to be
    100% correct it would need to be something like
    
    #ifndef SIZE_MAX
    #if SIZEOF_SIZE_T == 8
    #if SIZEOF_LONG == 8
    #define SIZE_MAX (18446744073709551615UL)
    #else /* assume unsigned long long is what we need */
    #define SIZE_MAX (18446744073709551615ULL)
    #endif
    #else /* 32-bit */
    #define SIZE_MAX (4294967295U)
    #endif
    #endif
    
    That's mighty ugly.  Is it worth the trouble, rather than trusting
    that the "(size_t) -1" trick will work?  Given that we have so few
    needs for SIZE_MAX, I'm kind of inclined just to stick with the cast.
    
    I notice BTW that PG_INT64_MIN, PG_INT64_MAX, and PG_UINT64_MAX
    all contain casts and thus are equally risky to test in #if-tests.
    I see no at-risk code in our tree right now, but someday we might
    need to make those look something like the above, too.
    
    			regards, tom lane
    
    
    
  5. Re: Missing SIZE_MAX

    Robert Haas <robertmhaas@gmail.com> — 2017-09-01T16:35:51Z

    On Fri, Sep 1, 2017 at 12:22 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
    > [ warning: more than you really wanted to know ahead ]
    
    It might be worth the effort to clean all of this up, just because the
    next person who gets bitten by it may not be as smart as you are.
    
    -- 
    Robert Haas
    EnterpriseDB: http://www.enterprisedb.com
    The Enterprise PostgreSQL Company
    
    
    
  6. Re: Missing SIZE_MAX

    Tom Lane <tgl@sss.pgh.pa.us> — 2017-09-01T16:49:28Z

    Robert Haas <robertmhaas@gmail.com> writes:
    > On Fri, Sep 1, 2017 at 12:22 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
    >> [ warning: more than you really wanted to know ahead ]
    
    > It might be worth the effort to clean all of this up, just because the
    > next person who gets bitten by it may not be as smart as you are.
    
    Yeah.  I was just thinking that maybe the appropriate investment of
    effort is to make [U]INT64CONST smarter, so that it results in a
    properly-suffixed constant and doesn't need a cast.  Then it'd be a
    lot easier to make these other macros be #if-safe.
    
    Or we could just recast the test in fe-exec.c to not use SIZE_MAX.
    Checking whether "SIZEOF_SIZE_T == 4" would really have the same
    effect, though it's uglier.
    
    			regards, tom lane
    
    
    
  7. Re: Missing SIZE_MAX

    Tom Lane <tgl@sss.pgh.pa.us> — 2017-09-01T18:25:32Z

    I wrote:
    > Robert Haas <robertmhaas@gmail.com> writes:
    >> It might be worth the effort to clean all of this up, just because the
    >> next person who gets bitten by it may not be as smart as you are.
    
    > Yeah.  I was just thinking that maybe the appropriate investment of
    > effort is to make [U]INT64CONST smarter, so that it results in a
    > properly-suffixed constant and doesn't need a cast.  Then it'd be a
    > lot easier to make these other macros be #if-safe.
    
    Actually, that looks easier than I thought.  The current approach to
    [U]INT64CONST dates to before we were willing to require the compiler
    to have working 64-bit support.  I think that now we can just assume
    that either an L/UL or LL/ULL suffix will work, as in the attached
    draft.  (This'd allow dropping configure's HAVE_LL_CONSTANTS probe
    entirely, but I didn't do that yet.)
    
    			regards, tom lane