Dear Turner, Before 1 year ago, Turner reported and marked that gxvalid can cause wrong validation by overflow in the calculation of 16bit offset, like:
offset_16bit = base_16bit + gid_16bit * const_32bit ; I'm quite sorry for long silence without fix the problem. Attached is the patch to detect the overflow, please let me know how do you think of. Masatake Yamato and me think: if too large 16bit GID causes overflow, calculated offset will be less than base_offset. So, ( offset_16bit < base_16bit ) can check the overflow. Unfortunately, both of Masatake Yamato and me don't have VC++ which you used to find problematic part of gxvalid, yet we don't know how VC++ warns about our fix. Regards, mpsuzuki P.S. Still there are several XXX parts in gxvalid, it will be fixed in 2007. Sorry. --- orig/src/gxvalid/gxvbsln.c +++ mod/src/gxvalid/gxvbsln.c @@ -131,9 +131,10 @@ FT_UShort offset; GXV_LookupValueDesc value; - /* XXX: check range ? */ - offset = (FT_UShort)( base_value.u + - ( relative_gindex * sizeof ( FT_UShort ) ) ); + offset = base_value.u + + relative_gindex * ( FT_UShort ) sizeof ( FT_UShort ); + if ( offset < base_value.u ) + FT_INVALID_OFFSET; p = valid->lookuptbl_head + offset; limit = lookuptbl_limit; --- orig/src/gxvalid/gxvcommn.c +++ mod/src/gxvalid/gxvcommn.c @@ -1400,9 +1400,10 @@ FT_UShort offset; GXV_LookupValueDesc value; - /* XXX: check range? */ - offset = (FT_UShort)( base_value.u + - relative_gindex * sizeof ( FT_UShort ) ); + offset = base_value.u + + relative_gindex * ( FT_UShort ) sizeof ( FT_UShort ); + if ( offset < base_value.u ) + FT_INVALID_OFFSET; p = valid->lookuptbl_head + offset; limit = lookuptbl_limit; --- orig/src/gxvalid/gxvlcar.c +++ mod/src/gxvalid/gxvlcar.c @@ -157,9 +157,11 @@ FT_UNUSED( lookuptbl_limit ); - /* XXX: check range? */ - offset = (FT_UShort)( base_value.u + - relative_gindex * sizeof ( FT_UShort ) ); + offset = base_value.u + + relative_gindex * ( FT_UShort ) sizeof ( FT_UShort ); + if ( offset < base_value.u ) + FT_INVALID_OFFSET; + p = valid->root->base + offset; limit = valid->root->limit; --- orig/src/gxvalid/gxvmort4.c +++ mod/src/gxvalid/gxvmort4.c @@ -87,9 +87,10 @@ FT_UShort offset; GXV_LookupValueDesc value; - /* XXX: check range? */ - offset = (FT_UShort)( base_value.u + - relative_gindex * sizeof ( FT_UShort ) ); + offset = base_value.u + + relative_gindex * ( FT_UShort ) sizeof ( FT_UShort ); + if ( offset < base_value.u ) + FT_INVALID_OFFSET; p = valid->lookuptbl_head + offset; limit = lookuptbl_limit; --- orig/src/gxvalid/gxvmorx1.c +++ mod/src/gxvalid/gxvmorx1.c @@ -179,9 +179,10 @@ FT_UShort offset; GXV_LookupValueDesc value; - /* XXX: check range? */ - offset = (FT_UShort)( base_value.u + - relative_gindex * sizeof ( FT_UShort ) ); + offset = base_value.u + + relative_gindex * ( FT_UShort ) sizeof ( FT_UShort ); + if ( offset < base_value.u ) + FT_INVALID_OFFSET; p = valid->lookuptbl_head + offset; limit = lookuptbl_limit; --- orig/src/gxvalid/gxvopbd.c +++ mod/src/gxvalid/gxvopbd.c @@ -141,9 +141,10 @@ FT_UNUSED( lookuptbl_limit ); FT_UNUSED( valid ); - /* XXX: check range? */ - value.u = (FT_UShort)( base_value.u + - relative_gindex * 4 * sizeof ( FT_Short ) ); + value.u = base_value.u + + relative_gindex * 4 * ( FT_UShort ) sizeof ( FT_Short ); + if ( value.u < base_value.u ) + FT_INVALID_OFFSET; return value; } --- orig/src/gxvalid/gxvprop.c +++ mod/src/gxvalid/gxvprop.c @@ -213,9 +213,11 @@ FT_UShort offset; GXV_LookupValueDesc value; - /* XXX: check range? */ - offset = (FT_UShort)( base_value.u + - relative_gindex * sizeof( FT_UShort ) ); + offset = base_value.u + + relative_gindex * ( FT_UShort ) sizeof( FT_UShort ); + if ( offset < base_value.u ) + FT_INVALID_OFFSET; + p = valid->lookuptbl_head + offset; limit = lookuptbl_limit; _______________________________________________ Freetype-devel mailing list Freetype-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/freetype-devel