question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Issue with SuRandomAccessFile and SuFile

See original GitHub issue

Hello John,

I tried few things with SuRandomAccessFile and I find an issue with SuFile.

Here is the code I tried which works fine with a File:

        try {
            SuRandomAccessFile file = SuRandomAccessFile.open(new File("/system/etc/hosts"), "r");
            String line;
            while ((line = file.readLine()) != null) {
                Log.e("TEST", line);
            }
        } catch (IOException e) {
            Log.e("TEST", "error", e);
        }

But if I use a SuFile instead of a java File:

        try {
            SuRandomAccessFile file = SuRandomAccessFile.open(new SuFile("/system/etc/hosts"), "r");
            String line;
            while ((line = file.readLine()) != null) {
                Log.e("TEST", line);
            }
        } catch (IOException e) {
            Log.e("TEST", "error", e);
        }

I always got an error:

2020-08-16 11:44:24.736 21996-21996/com.topjohnwu.libsuexample D/LIBSU: java.io.InterruptedIOException
        at com.topjohnwu.superuser.internal.ShellImpl$DefaultTask.run(ShellImpl.java:280)
        at com.topjohnwu.superuser.internal.ShellImpl.execTask(ShellImpl.java:233)
        at com.topjohnwu.superuser.internal.JobImpl.exec0(JobImpl.java:53)
        at com.topjohnwu.superuser.internal.JobImpl.exec(JobImpl.java:70)
        at com.topjohnwu.libsuexample.MainActivity$ExampleInitializer.onInit(MainActivity.java:84)
        at com.topjohnwu.superuser.internal.BuilderImpl.build(BuilderImpl.java:84)
        at com.topjohnwu.superuser.internal.BuilderImpl.build(BuilderImpl.java:58)
        at com.topjohnwu.superuser.internal.MGR.getShell(MGR.java:41)
        at com.topjohnwu.superuser.Shell.getShell(Shell.java:148)
        at com.topjohnwu.superuser.ShellUtils.fastCmdResult(ShellUtils.java:85)
        at com.topjohnwu.superuser.io.SuFile.cmdBool(SuFile.java:110)
        at com.topjohnwu.superuser.io.SuFile.exists(SuFile.java:184)
        at com.topjohnwu.superuser.internal.ShellIO.<init>(ShellIO.java:57)
        at com.topjohnwu.superuser.internal.ShellIO.get(ShellIO.java:75)
        at com.topjohnwu.superuser.internal.IOFactory.createShellIO(IOFactory.java:41)
        at com.topjohnwu.superuser.io.SuRandomAccessFile.open(SuRandomAccessFile.java:54)
        at com.topjohnwu.libsuexample.MainActivity.runIoTests(MainActivity.java:244)
        at com.topjohnwu.libsuexample.MainActivity.lambda$onCreate$5$MainActivity(MainActivity.java:219)
        at com.topjohnwu.libsuexample.-$$Lambda$MainActivity$a7zsI796bNp0TD7tk4yhXst0ak4.onClick(Unknown Source:2)
        at android.view.View.performClick(View.java:7259)
        at android.view.View.performClickInternal(View.java:7236)
        at android.view.View.access$3600(View.java:801)
        at android.view.View$PerformClick.run(View.java:27892)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
     Caused by: java.util.concurrent.ExecutionException: java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.length()' on a null object reference
        at java.util.concurrent.FutureTask.report(FutureTask.java:123)
        at java.util.concurrent.FutureTask.get(FutureTask.java:193)
        at com.topjohnwu.superuser.internal.ShellImpl$DefaultTask.run(ShellImpl.java:277)
        at com.topjohnwu.superuser.internal.ShellImpl.execTask(ShellImpl.java:233) 
        at com.topjohnwu.superuser.internal.JobImpl.exec0(JobImpl.java:53) 
        at com.topjohnwu.superuser.internal.JobImpl.exec(JobImpl.java:70) 
        at com.topjohnwu.libsuexample.MainActivity$ExampleInitializer.onInit(MainActivity.java:84) 
        at com.topjohnwu.superuser.internal.BuilderImpl.build(BuilderImpl.java:84) 
        at com.topjohnwu.superuser.internal.BuilderImpl.build(BuilderImpl.java:58) 
        at com.topjohnwu.superuser.internal.MGR.getShell(MGR.java:41) 
        at com.topjohnwu.superuser.Shell.getShell(Shell.java:148) 
        at com.topjohnwu.superuser.ShellUtils.fastCmdResult(ShellUtils.java:85) 
        at com.topjohnwu.superuser.io.SuFile.cmdBool(SuFile.java:110) 
        at com.topjohnwu.superuser.io.SuFile.exists(SuFile.java:184) 
        at com.topjohnwu.superuser.internal.ShellIO.<init>(ShellIO.java:57) 
        at com.topjohnwu.superuser.internal.ShellIO.get(ShellIO.java:75) 
        at com.topjohnwu.superuser.internal.IOFactory.createShellIO(IOFactory.java:41) 
        at com.topjohnwu.superuser.io.SuRandomAccessFile.open(SuRandomAccessFile.java:54) 
        at com.topjohnwu.libsuexample.MainActivity.runIoTests(MainActivity.java:244) 
        at com.topjohnwu.libsuexample.MainActivity.lambda$onCreate$5$MainActivity(MainActivity.java:219) 
        at com.topjohnwu.libsuexample.-$$Lambda$MainActivity$a7zsI796bNp0TD7tk4yhXst0ak4.onClick(Unknown Source:2) 
        at android.view.View.performClick(View.java:7259) 
        at android.view.View.performClickInternal(View.java:7236) 
        at android.view.View.access$3600(View.java:801) 
        at android.view.View$PerformClick.run(View.java:27892) 
        at android.os.Handler.handleCallback(Handler.java:883) 
        at android.os.Handler.dispatchMessage(Handler.java:100) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.app.ActivityThread.main(ActivityThread.java:7356) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.length()' on a null object reference
        at com.topjohnwu.superuser.internal.StreamGobbler.isEOS(StreamGobbler.java:46)
        at com.topjohnwu.superuser.internal.StreamGobbler$OUT.call(StreamGobbler.java:77)
        at com.topjohnwu.superuser.internal.StreamGobbler$OUT.call(StreamGobbler.java:66)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)

It comes from the StreamGobbler which tries to find the EOS when the BufferedReader reaches EOF first. I think it does not find the eos tag and isEOS fails.

Moreover, there is something strange with the isEOS implementation:

protected boolean isEOS(String line) {
        boolean eof = false;
        int sl = line.length() - 1;
        int tl = eos.length() - 1;
        if (sl >= tl) {
            eof = true;
            for (; tl >= 0; --tl, --sl) {
                if (eos.charAt(tl) != line.charAt(sl)) {
                    eof = false;
                    break;
                }
            }
            if (eof)
                line = sl >= 0 ? line.substring(0, sl + 1) : null;
        }
        if (list != null && line != null) {
            list.add(line);
            Utils.log(TAG, line);
        }
        return eof;
    }

line is never tested to be null at method start where it can becomes null and nullability is checked later.

Long story short: I might be using SuFile the wrong way. If not, there might be a bug with SuRandomAccessFile

Regards, Bruce

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:10 (9 by maintainers)

github_iconTop GitHub Comments

1reaction
PerfectSlayercommented, Aug 23, 2020

I add a log into the com.topjohnwu.superuser.internal.StreamGobbler.OUT#call method to dump read lines and here is the result:

Device API:  
Device ABI: arm
  

I seem the com.topjohnwu.libsuexample.MainActivity.ExampleInitializer load a script and it fails to load/parse. You can see it runs some calls from the test_sync shell method. So the shell outputs error and seems to fail SuFile operations.

I also add a log into the com.topjohnwu.superuser.internal.StreamGobbler.ERR#call and I got a lot of errors:

sh: 
: not found
sh: shift
: not found
head: invalid number '1
'
sh: }
: not found
sh: 
: not found
sh: {
: not found
sh: {
: not found
sh: {
: not found
sh: {
: not found
sh: 
: not found
sh: 
: not found
sh: 
: not found
sh: 
: not found
sh: 
: not found
sh: }
: not found
sh: 
: not found
sh: api_level_arch_detect
: not found
sh: }
: not found
sh: 
: not found
sh: syntax error: unexpected word (expecting "do")

Is it working on your side?

EDIT: I just discover the whole example app is not working if I keep the bash.rc ExampleInitializer. I never had test / output from in the main screen when pressing test buttons. Removing it make the test feature work.

For the record, here is my configuration:

  • Device: Pixel 2 / QQ3A.200705.002
  • Magisk: 20.4 (patched boot from manager the fastboot flashed)
  • Magisk Manager: 7.5.1
0reactions
PerfectSlayercommented, Feb 6, 2021

Thanks for the fix, it should do the trick! 👍 There is another issue with you build script when building on Windows, I will make an issue to address it.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Issue with "import java.io.RandomAccessFile;" - Stack Overflow
I can't access your links but apparently you have named your class as RandomAccessFile ? If so try to change its name, because...
Read more >
Problem with RandomAccessFile - CodeRanch
Hi,. Can anyone tell my why I do get -1393754107 with this code instead of 1 .
Read more >
RandomAccessFile (Java Platform SE 8 ) - Oracle Help Center
A random access file behaves like a large array of bytes stored in the file system. There is a kind of cursor, or...
Read more >
Java RandomAccessFile Example - DigitalOcean
RandomAccessFile works with file as large array of bytes stored in the file system and a cursor using which we can move the...
Read more >
Read a Record from a Random Access File using Java (Simple)
Read a Record from a Random Access File using JavaGreetings, today I shall show how to read a record from a file using...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found