[geos-devel] [GEOS] #869: CommonBits::zeroLowerBits undefined behavior

GEOS geos-trac at osgeo.org
Wed Sep 18 06:34:54 PDT 2019


#869: CommonBits::zeroLowerBits undefined behavior
-------------------------------+---------------------------
 Reporter:  goatbar            |       Owner:  geos-devel@…
     Type:  defect             |      Status:  reopened
 Priority:  minor              |   Milestone:  3.6.4
Component:  Default            |     Version:  3.6.2
 Severity:  Unassigned         |  Resolution:
 Keywords:  UndefinedBehavior  |
-------------------------------+---------------------------
Changes (by rouault):

 * status:  closed => reopened
 * resolution:  fixed =>


Comment:

 Actually, the fix is incorrect for several reasons:
 - (1<< nBits)-1  has only int operands, so will be evaluated on 32 bit
 only. Consequently nBits >= 32 will result in incorrect behaviour, unless
 you cast the first 1 to int64 :  ((int64)1 << nBits) - 1
 - but, if let to 32 bits ( (1<< nBits)-1 ), then nBits == 31 is also an
 invalid input (-fsanitize=undefined warns about "runtime error: left shift
 of 1 by 31 places cannot be represented in type 'int'") even if "sane"
 compilers / most CPUs will finally do the right thing. The right fix in
 that case to avoid undefined/implementation defined behaviour is to use a
 unsigned 1, so (1U << nBits) - 1
 - for the same reason, is the mask is intended to be a 64 bit one, so
 ((int64)1 << nBits) - 1), then nBits == 63 also triggers undefined
 behaviour. And thus the right fix would be ((unsigned int64)1 << nBits) -
 1

-- 
Ticket URL: <https://trac.osgeo.org/geos/ticket/869#comment:5>
GEOS <http://trac.osgeo.org/geos>
GEOS (Geometry Engine - Open Source) is a C++ port of the Java Topology Suite (JTS).


More information about the geos-devel mailing list