{"record":{"id":"2a4c48b484bf9b19","repo":"NationalSecurityAgency/ghidra","slug":"invalid-number-of-elements-specified","errorCode":null,"errorMessage":"Invalid number of elements specified: {}","messagePattern":"Invalid number of elements specified: (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"GPL/DMG/src/dmg/java/mobiledevices/dmg/ghidra/GBinaryReader.java","lineNumber":641,"sourceCode":"     * @return the LONG\n     * @exception IOException if an I/O error occurs\n     */\n    public long readLong(long index, long minClamp, long maxClamp, Long... exceptions) throws IOException {\n        long l = readLong(index);\n        return clampLong(l, minClamp, maxClamp, exceptions);\n    }\n\n    /**\n     * Returns the BYTE array of <code>nElements</code>\n     * starting at <code>index</code>.\n     * @param index the index where the BYTE begins\n     * @param nElements the number of array elements\n     * @return the BYTE array\n     * @exception IOException if an I/O error occurs\n     */\n    public byte [] readByteArray(long index, int nElements) throws IOException {\n        if (nElements < 0) {\n            throw new IOException(\"Invalid number of elements specified: \"+nElements);\n        }\n        return provider.readBytes(index, nElements);\n    }\n\n    /**\n     * Returns the BYTE array of <code>nElements</code>\n     * starting at <code>index</code>.\n     * @param index the index where the BYTE begins\n     * @param nElements the number of array elements\n     * @return the BYTE array\n     * @exception IOException if an I/O error occurs\n     */\n    public byte [] readByteArray(long index, int nElements, byte minClamp, byte maxClamp, Byte... exceptions) throws IOException {\n        byte[] array = readByteArray(index, nElements);\n        for (int ii = 0; ii < array.length; ++ii) {\n            array[ii] = clampByte(array[ii], minClamp, maxClamp, exceptions);\n        }\n        return array;","sourceCodeStart":623,"sourceCodeEnd":659,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/GPL/DMG/src/dmg/java/mobiledevices/dmg/ghidra/GBinaryReader.java#L623-L659","documentation":"GBinaryReader.readByteArray(long index, int nElements) rejects a negative element count before delegating to provider.readBytes. It is a precondition guard: the caller passed a count that cannot correspond to a real array length, so the library fails fast rather than producing a NegativeArraySizeException downstream (new byte[nElements]).","triggerScenarios":"Calling readByteArray(index, n) where n is negative. This typically happens when nElements is computed from a parsed length field that was read with the wrong size, wrong endianness, or from a corrupt/truncated structure that yielded -1 or a wrapped negative value.","commonSituations":"A parsed 'count' field read as a signed value that overflowed; reading a length from an endianness-mismatched header; passing an uninitialized or sentinel (-1) length straight into the array reader; truncated input where a length field is missing.","solutions":["Check nElements >= 0 at the call site and trace where the negative value originated (log it before calling).","Verify the field supplying nElements is read with the correct size and endianness (use the matching readShort/readInt vs. unsigned variants).","Guard against sentinel/unknown (-1) lengths by mapping them to 0 or skipping the read instead of passing them through.","Validate the parsed structure's length fields against known bounds before indexing."],"exampleFix":"// before\nbyte[] data = reader.readByteArray(offset, parsedCount);\n\n// after\nif (parsedCount < 0) {\n    throw new IOException(\"Invalid parsed length \" + parsedCount + \" at offset \" + offset);\n}\nbyte[] data = reader.readByteArray(offset, parsedCount);","handlingStrategy":"validation","validationCode":"if (nElements < 0) {\n    throw new IllegalArgumentException(\"nElements must be >= 0, got \" + nElements);\n}\nbyte[] data = reader.readByteArray(index, nElements);","typeGuard":"private static boolean isNonNegativeCount(int n) { return n >= 0; }","tryCatchPattern":"try {\n    return reader.readByteArray(index, nElements);\n} catch (IOException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Invalid number of elements\")) {\n        throw new IllegalArgumentException(\"readByteArray got negative count\", e);\n    }\n    throw e;\n}","preventionTips":["Bounds-check every parsed length field before passing it to an array reader.","Read count fields with the exact width and endianness the format specifies.","Map sentinel/unknown lengths (-1) to 0 or skip the read rather than forwarding them."],"tags":["dmg","binary-reader","validation","parsing","corrupt-file"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}