Describe the issue:
Some thumbhashes generated by datocms cause both the expo-image and reference (github.com/evanw/thumbhash) Swift decoder to crash. It also appears to fail to render an image on java/android implementation. The web implementation is ok, due to a quirk of the JS language.
Can you provide a link to the item, model, or project in question?
The hash that breaks is CwgGH4Z3q3cgd2SkW3mHqVh3R8YJZYs=
generated from https://www.datocms-assets.com/107161/1699353334-adults-manage-emotions.png
Do you have any sample code you can provide?
Run this fork of the reference example iOS project here: https://github.com/Royce/thumbhash/tree/main/examples/ios/Example.xcodeproj β I have hard coded the problematic thumbhash if you want to see it crash.
This is the line that crashes: swift/ThumbHash.swift#L287
let decodeChannel = { (nx: Int, ny: Int, scale: Float32) -> [Float32] in
var ac: [Float32] = []
for cy in 0 ..< ny {
var cx = cy > 0 ? 0 : 1
while cx * ny < nx * (ny - cy) {
>>> let iac = (hash[ac_start + (ac_index >> 1)] >> ((ac_index & 1) << 2)) & 15;
var fac = Float32(iac)
fac = (fac / 7.5 - 1) * scale
ac.append(fac)
ac_index += 1
cx += 1
}
}
return ac
}
Specifically, hash[ac_start + (ac_index >> 1)]
is hash[23]
is an out of bounds error.
The javascript implementation is ok, but only because javascript is weird
In the javascript implementation (js/thumbhash.js#L128
) the code hash[ac_start + (ac_index >> 1)]
is undefined and (hash[ac_start + (ac_index >> 1)] >> ((ac_index++ & 1) << 2)
is undefined >> 4
is 0 >> 4
β so the missing data from hash
is treated as 0
let decodeChannel = (nx, ny, scale) => {
let ac = []
for (let cy = 0; cy < ny; cy++)
for (let cx = cy ? 0 : 1; cx * ny < nx * (ny - cy); cx++)
ac.push((((hash[ac_start + (ac_index >> 1)] >> ((ac_index++ & 1) << 2)) & 15) / 7.5 - 1) * scale)
return ac
}
Workaround and possible solution
The problem hash is:
CwgGH4Z3q3cgd2SkW3mHqVh3R8YJZYs=
β 0b 08 06 1f 86 77 ab 77 20 77 64 a4 5b 79 87 a9 58 77 47 c6 09 65 8b
Changing this to the following avoids the issue:
CwgGH4Z3q3cgd2SkW3mHqVh3R8YJZYsA
β 0b 08 06 1f 86 77 ab 77 20 77 64 a4 5b 79 87 a9 58 77 47 c6 09 65 8b 00
< note the extra 00
Itβs worth noting that if I take this image (/107161/1699353334-adults-manage-emotions.png) and generate a thumbhash using the demo website (evanw.github.io/thumbhash
) I get the following very similar hash that explicitly also encodes the final 00
.
CwgGH4Z3qncgd2SkW3mHqVh3R8YJZYsA
=> 0B 08 06 1F 86 77 AA 77 20 77 64 A4 5B 79 87 A9 58 77 47 C6 09 65 8B 00