BufferedInputStream Causing undetermined behavior on android

Hello,

A test for Bin Enhancement as requested by Ali @Ali_RS on Android shows this exception :

E/AndroidRuntime: FATAL EXCEPTION: GLThread 3459
    Process: com.scrappers.dbcodecamp, PID: 9321
    com.jme3.asset.AssetLoadException: An exception has occurred while loading asset: AssetsForRenderer/Textures/sky.jpg (Flipped) (Mipmapped)
        at com.jme3.asset.DesktopAssetManager.loadLocatedAsset(DesktopAssetManager.java:274)
        at com.jme3.asset.DesktopAssetManager.loadAsset(DesktopAssetManager.java:388)
        at com.jme3.asset.DesktopAssetManager.loadTexture(DesktopAssetManager.java:407)
        at com.jme3.asset.DesktopAssetManager.loadTexture(DesktopAssetManager.java:419)
        at com.scrappers.dbtraining.mainScreens.prefaceScreen.renderer.Environment.initialize(Environment.java:83)
        at com.jme3.app.state.BaseAppState.initialize(BaseAppState.java:132)
        at com.jme3.app.state.AppStateManager.initializePending(AppStateManager.java:333)
        at com.jme3.app.state.AppStateManager.update(AppStateManager.java:363)
        at com.jme3.app.SimpleApplication.update(SimpleApplication.java:256)
        at com.jme3.app.jmeSurfaceView.JmeSurfaceView.update(JmeSurfaceView.java:190)
        at com.jme3.system.android.OGLESContext.onDrawFrame(OGLESContext.java:350)
        at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1574)
        at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1273)
     Caused by: java.io.IOException: Could not skip requested number of bytes
        at com.jme3.texture.plugins.AndroidNativeImageLoader.load(Native Method)
        at com.jme3.texture.plugins.AndroidNativeImageLoader.load(AndroidNativeImageLoader.java:34)
        at com.jme3.texture.plugins.AndroidNativeImageLoader.load(AndroidNativeImageLoader.java:20)
        at com.jme3.asset.DesktopAssetManager.loadLocatedAsset(DesktopAssetManager.java:272)
        at com.jme3.asset.DesktopAssetManager.loadAsset(DesktopAssetManager.java:388) 
        at com.jme3.asset.DesktopAssetManager.loadTexture(DesktopAssetManager.java:407) 
        at com.jme3.asset.DesktopAssetManager.loadTexture(DesktopAssetManager.java:419) 
        at com.scrappers.dbtraining.mainScreens.prefaceScreen.renderer.Environment.initialize(Environment.java:83) 
        at com.jme3.app.state.BaseAppState.initialize(BaseAppState.java:132) 
        at com.jme3.app.state.AppStateManager.initializePending(AppStateManager.java:333) 
        at com.jme3.app.state.AppStateManager.update(AppStateManager.java:363) 
        at com.jme3.app.SimpleApplication.update(SimpleApplication.java:256) 
        at com.jme3.app.jmeSurfaceView.JmeSurfaceView.update(JmeSurfaceView.java:190) 
        at com.jme3.system.android.OGLESContext.onDrawFrame(OGLESContext.java:350) 
        at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1574) 
        at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1273) 

Caused by: java.io.IOException: Could not skip requested number of bytes

I am not a jni specialist, but seems this exception is raised due to the fact that the native streams don’t support seeking bytes, and has a way to block that malicious activity of reading over & skipping bytes which i suspect is caused by BufferedInputStream#fill() so either read the whole file(in bytes) or skip the whole file(in bytes), if the skipped bytes are abstract of the file size then the error is raised, the code that raises that :

But this works fine, since java has no way of maliciously read & skip over bytes :

@Override
    public Image load(AssetInfo info) throws IOException {
        boolean flip = ((TextureKey) info.getKey()).isFlipY();
        try (final InputStream stream = info.openStream()) {
            return load(stream, flip, tmpArray);
        }
    }

For android, the current reading of textures is managed by the JNI Invocation api using wrapper.isReadMethod = (*env)->GetMethodID(env, inputStreamClass, "read", "([BII)I"); using plain InputStreams or its subclasses so we cannot read or skip from the java side as BIN may have do.

1 Like

@Pavl_G thanks for testing it.

Here is the related PR that cause the issue in case someone wants to take a look:

1 Like