treeform/pixie

fillPath fails with unhandled RangeDefect exception

kwhitefoot opened this issue · 1 comments

I got fed up with my prototype genetic drawing program throwing exceptions because it gave bad paths to pixie. So I wrote a little program to try to find out what paths don't work. A bit like fuzzing except that I don't know how to do that properly so I opted to simply try every combination of a few numbers. It worked and found some unhandled exceptions but so far no crashes.

Here are a few of the paths that cause unhandled exceptions:

Unhandled error in pixie:
value out of range: -9223372036854775808 notin 0 .. 9223372036854775807
i: 1346a85
pathStr: M -3.402823561222554e+19 -3.402823561222554e+19 L -3.402823561222554e+19 -3.402823561222554e+19 C -3402823424.0 -3402823424.0 -3.402823561222554e+19 -3.402823561222554e+19 -3402.823486328125 -3402.823486328125 A -3402.823486328125 -3402.823486328125 -3402.823486328125 0 0 -3.402823561222554e+19 -3.402823561222554e+19
Unhandled error in pixie:
value out of range: -9223372036854775808 notin 0 .. 9223372036854775807
i: 1346a92
pathStr: M -3.402823561222554e+19 -3.402823561222554e+19 L -3.402823561222554e+19 -3.402823561222554e+19 C -3402823424.0 -3402823424.0 -3.402823561222554e+19 -3.402823561222554e+19 -3402.823486328125 -3402.823486328125 A -3402.823486328125 -3402.823486328125 -3402.823486328125 0 0 -3402.823486328125 -3402.823486328125
Unhandled error in pixie:
value out of range: -9223372036854775808 notin 0 .. 9223372036854775807
i: 1346a93
pathStr: M -3.402823561222554e+19 -3.402823561222554e+19 L -3.402823561222554e+19 -3.402823561222554e+19 C -3402823424.0 -3402823424.0 -3.402823561222554e+19 -3.402823561222554e+19 -3402.823486328125 -3402.823486328125 A -3402.823486328125 -3402.823486328125 -3402.823486328125 0 1 -3.402823561222554e+19 -3.402823561222554e+19
Unhandled error in pixie:
value out of range: -9223372036854775808 notin 0 .. 9223372036854775807
i: 1346aa0
pathStr: M -3.402823561222554e+19 -3.402823561222554e+19 L -3.402823561222554e+19 -3.402823561222554e+19 C -3402823424.0 -3402823424.0 -3.402823561222554e+19 -3.402823561222554e+19 -3402.823486328125 -3402.823486328125 A -3402.823486328125 -3402.823486328125 -3402.823486328125 0 1 -3402.823486328125 -3402.823486328125
Unhandled error in pixie:
value out of range: -9223372036854775808 notin 0 .. 9223372036854775807
i: 1346aa1
pathStr: M -3.402823561222554e+19 -3.402823561222554e+19 L -3.402823561222554e+19 -3.402823561222554e+19 C -3402823424.0 -3402823424.0 -3.402823561222554e+19 -3.402823561222554e+19 -3402.823486328125 -3402.823486328125 A -3402.823486328125 -3402.823486328125 -3402.823486328125 0 0 -3.402823561222554e+19 -3.402823561222554e+19

The program echoes every path that cause an exception that pixie doesn't handle.

Edit: I discovered an embarrassing bug in my code, here is an improved version:

# An attempt at, sort of, fuzzing pixie.

import pixie, chroma

import strformat
import strutils
import bigints
#import std/options


let
  image = newImage(200, 200)
image.fill(rgba(255, 255, 255, 255))

const
  argCount = 18
  maxFloat = 3.4028235e38.float32
  halfMaxFloat = 3.4028235e19.float32
  quarterMaxFloat = 3.4028235e9.float32
  tenthMaxFloat = 3.4028235e3.float32
  thousand = 1000.float32
  ten = 10.float32
  a = [-halfMaxFloat, -quarterMaxFloat, -tenthMaxFloat, -thousand, -ten, 
       0,
       ten, thousand, tenthMaxFloat, quarterMaxFloat, halfMaxFloat]
  base = a.high - a.low + 1
  ai: array[base, int] =  [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]
  m = "1000000000000000000".initBigInt(base)
  #     012345678901234567890

var
  paint = newPaint(SolidPaint)

paint.color = color(255, 255, 255, 255)
  
var
  i = 0.initBigInt()

#i = "10244424".initBigInt(base)

#i = "222220000".initBigInt(base)

while i < m:
  var
    n: array[argCount, int]
    s = i.toString(3).align(argCount, '0')
    
  for j in 0 ..< argCount:
    let
      c = s[j]
    if c in '0'..'9':
       n[j] = int(c) - int('0')
    else:
       n[j] = int(c) - int('a') + 10

      #debugEcho &"n: {n}"
  
  let
    pathStr = &"""M {a[n[0]]} {a[n[1]]} L {a[n[2]]} {a[n[3]]} C {a[n[4]]} {a[n[5]]} {a[n[7]]} {a[n[8]]} {a[n[9]]} {a[n[10]]} A {a[n[11]]} {a[n[12]]} {a[n[13]]} {ai[n[14]]} {ai[n[15]]} {a[n[16]]} {a[n[17]]}"""

  let
     path = parsePath(pathStr)
  try:
    fillPath(image,
             path,
             paint,
             mat3(),
             NonZero)
  except PixieError:
    #echo "Handled error in pixie"
    #echo getCurrentExceptionMsg()
    discard
  except:
    echo "Unhandled error in pixie:"
    echo getCurrentExceptionMsg()
    echo &"i: {i.toString(base)}"
    echo &"pathStr: {pathStr}"
    
  i += 1

echo "Finished"
guzba commented

I've added a check for the cause of the errors here (integer overflow). After adding the checks it stopped taking the unhandled error path. This is merged into master but not yet tagged in a release of Pixie.