{"record":{"id":"5c44490ecb905989","repo":"LSPosed/LSPosed","slug":"length-length-is-out-of-range-for-filename","errorCode":null,"errorMessage":"Length ${length} is out of range for ${filename}","messagePattern":"Length (.+?) is out of range for (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/de/robv/android/xposed/services/DirectAccessService.java","lineNumber":100,"sourceCode":"        if (length > 0 && (offset + length) > size) {\n            throw new IllegalArgumentException(\"Length \" + length + \" is out of range for \" + filename);\n        } else if (length <= 0) {\n            length = (int) (size - offset);\n        }","sourceCodeStart":null,"sourceCodeEnd":null,"githubUrl":"https://github.com/LSPosed/LSPosed/blob/df74d83eb03a44cc6ad268841ac2ada28d077c77/core/src/main/java/org/lsposed/lspd/services/DirectAccessService.java#L100","documentation":"The same ranged readFile method in DirectAccessService throws IllegalArgumentException when offset + length exceeds the file size (line 99). The implementation allocates byte[length] and does a single fis.read(content), so a length running past EOF would silently return a short read; the API rejects it up front instead.","triggerScenarios":"Calling readFile(path, offset, length, prevSize, prevTime) with length > size - offset, e.g. offset=10, length=100 on a 50-byte file, or when the file shrank between stat and read.","commonSituations":"Hardcoded chunk sizes for reading structured files whose actual size is smaller than expected; reading with stale cached length after the file was truncated.","solutions":["Query statFile first and clamp length to (int)(size - offset)","Pass length <= 0 to mean 'rest of the file' — the implementation then computes length = size - offset itself","If chunking large files, compute each chunk from the fresh size, not a cached one"],"exampleFix":"// before\nFileResult r = service.readFile(path, offset, 4096, prevSize, prevTime);\n\n// after\nFileResult st = service.statFile(path);\nint len = (int) Math.min(4096, st.size - offset);\nFileResult r = service.readFile(path, offset, len, st.size, st.mtime);","handlingStrategy":"validation","validationCode":"FileResult st = service.statFile(filename);\nif (length > st.size - offset) {\n    length = (int) (st.size - offset); // clamp to EOF\n}","typeGuard":null,"tryCatchPattern":"try {\n    return service.readFile(filename, offset, length, prevSize, prevTime);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Length\")) {\n        return service.readFile(filename, offset, 0, prevSize, prevTime); // length<=0 = rest of file\n    }\n    throw e;\n}","preventionTips":["Compute chunk lengths from a fresh size, never a cached constant","Pass length <= 0 when you mean 'to end of file' — the service clamps for you","Chunk readers should re-stat when (size, mtime) changes"],"tags":["io","file-access","range-check","validation","argument-error"],"backgroundTag":null,"analyzedSha":"df74d83eb03a44cc6ad268841ac2ada28d077c77","analyzedAt":"2026-08-14T10:46:48.326Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}