Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error: unhandled exception: cannot read from stream [IOError] #55

Closed
ThomasTJdev opened this issue Sep 25, 2020 · 4 comments
Closed

Error: unhandled exception: cannot read from stream [IOError] #55

ThomasTJdev opened this issue Sep 25, 2020 · 4 comments

Comments

@ThomasTJdev
Copy link

When trying to parse large base64-string's I get the error:

Error: unhandled exception: cannot read from stream [IOError]

The base64-string origins from photos taken with iPhones, which then is converted to base64 in the browser. I can't reproduce exactly when this happens, so my guessing is, that it might be due to the details in the photo (?).

I have the base64-strings which works flawless with online converters and linux own base64 -d p.txt >> p.png. I have also validated the base64-string, and it is valid base64.

Test code:

import base64, streams
import nimPNG

const b = """loooong base64"""

proc fromBase64(input: string): string =
  result = base64.decode(input)

proc base64ToPng*(b64: string, path: string): bool =
  let
    s = newStringStream(fromBase64(b64))
    decoded = s.decodePNG(LCT_RGBA, 8) # <== This one, line 12

  result = (savePNG32(path, decoded.data, decoded.width, decoded.height))

echo base64ToPng(b, "debug.png")

GH does not like the long base64 string so here is a Gist with it: https://gist.github.com/ThomasTJdev/7a14a8b8309d67a7188c3cfe61eff869

The error message is:

/home/user/tmp/nim/image/base64debug.nim(22) base64debug
/home/user/tmp/nim/image/base64debug.nim(17) base64ToPng
/home/user/.nimble/pkgs/nimPNG-0.3.1/nimPNG.nim(1917) decodePNG
/home/user/.nimble/pkgs/nimPNG-0.3.1/nimPNG.nim(1842) decodePNG
/home/user/.nimble/pkgs/nimPNG-0.3.1/nimPNG.nim(939) parsePNG
/home/user/.nimble/pkgs/nimPNG-0.3.1/nimPNG.nim(387) readInt32BE
/home/user/.choosenim/toolchains/nim-1.2.6/lib/pure/streams.nim(570) readInt32
/home/user/.choosenim/toolchains/nim-1.2.6/lib/pure/streams.nim(382) read
Error: unhandled exception: cannot read from stream [IOError]
@ThomasTJdev
Copy link
Author

And this is also present if I:

import base64
import nimPNG

const b = """looong base64"""

writeFile("debug.png",base64.decode(b))
let png = loadPNG("debug.png", LCT_RGBA, 8)

# = > cannot read from stream

@ThomasTJdev
Copy link
Author

ThomasTJdev commented Sep 25, 2020

Okay, I had not thought about checking the output image. Using imagemagic convert gives some info on the image created using linux base64. This indicates, that it's my base64-string which is faulty.

$ convert
Expected 8192 bytes; found 7782 bytes

$ pngcheck -7cv debug.png
File: debug.png (393216 bytes)
  chunk IHDR at offset 0x0000c, length 13
    370 x 493 image, 32-bit RGB+alpha, non-interlaced
  chunk sRGB at offset 0x00025, length 1
    rendering intent = perceptual
  chunk eXIf at offset 0x00032, length 68:  illegal (unless recently approved) unknown, public chunk
ERRORS DETECTED in debug.png

@ThomasTJdev
Copy link
Author

Closed due to my previous comment. It must be my base64 which is malformed.

@jangko
Copy link
Owner

jangko commented Oct 3, 2020

Thank you for reporting this.
I've investigate it. Turn out it is an incomplete png file and therefore according to the spec it is an invalid input.
But I also tested with some other png decoder and they seem ignoring the incomplete part and continue decoding.
The result is of course an incomplete image or image with blank/random/uninitialized pixels of that skipped chunk.

I think it is a good idea to also implement this so called 'relaxed' parsing mode along with 'strict' parsing mode.
nimBMP and libzip are examples of libs that try to recover as much as possible data from a corrupted input file.

PNG format consist of chunks of loosely coupled data, if the parser can work in recovery mode perhaps using some progressive scanning method, we can increase the robustness of nimPNG.

Technically this is not nimPNG bug, so I will open a new issue and mark it as new feature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants