[fpc-devel] Dangerous optimization in CASE..OF

Martok listbox at martoks-place.de
Sun Jul 2 14:30:28 CEST 2017


> Yes, checking the data. I can easily create a similar problem as above with the "range checks" for
> the jump table by reading a negative value into the enum. Unfortunately, the checks are unsigned ...
Actually, fun fact, *fortunately* the checks are unsigned. Having a negative
value (or generally a value before the first element when that has a value
assignment) underflows on the check, and so gets caught by the CMP/JA as well.
Yes, I tried that, your code is safer than you think ;-)

Also, for sparse enums the "gaps" are filled with pointers to else-block, so the
check that is already there turns out to be always safe.

enum = (ela = 5, elb, elc, eld, ele);

1) enum value too small ( = 1):

   mov    1,%al
   sub    5,%al           # al = -4 = $fb
   cmp    (9-5),%al       # $fb > 4
   ja     $#ELSE-BLOCK    # branches
   and    $ff,%eax
   jmp    *0x40c000(,%eax,4)

2) enum value in range or in gap (= 7 = elc)

   mov    7,%al
   sub    5,%al           # al = 2
   cmp    (9-5),%al       # 2 <= 4
   ja     $#ELSE-BLOCK    # no branch
   and    $ff,%eax
   jmp    *0x40c000(,%eax,4)

3) enum value too large ( = 20)

   mov    20,%al
   sub    5,%al           # al = 15
   cmp    (9-5),%al       # 15 > 4
   ja     $#ELSE-BLOCK    # branches
   and    $ff,%eax
   jmp    *0x40c000(,%eax,4)


Same thing on x86_64, where instead of al and eax we use eax and rax, with the
same underflow characteristics.




More information about the fpc-devel mailing list