{"record":{"id":"a84ce6cc966ef911","repo":"Anuken/Mindustry","slug":"invalid-array-size-a84ce6","errorCode":null,"errorMessage":"Invalid array size: ","messagePattern":"Invalid array size: ","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"core/src/mindustry/io/TypeIO.java","lineNumber":248,"sourceCode":"            //unit command\n            case 15 -> {\n                read.b();\n                yield null;\n            }\n            case 16 -> {\n                if(!allowArrays) throw new RuntimeException(\"Nested arrays are not allowed\");\n                int len = read.i();\n                if(len > maxArraySize) throw new RuntimeException(\"Invalid array size: \" + len);\n\n                boolean[] bools = new boolean[len];\n                for(int i = 0; i < len; i ++) bools[i] = read.bool();\n                yield bools;\n            }\n            case 17 -> !box ? Groups.unit.getByID(read.i()) : new UnitBox(read.i());\n            case 18 -> {\n                if(!allowArrays) throw new RuntimeException(\"Nested arrays are not allowed\");\n                int len = read.s();\n                if(len > maxArraySize) throw new RuntimeException(\"Invalid array size: \" + len);\n\n                Vec2[] out = new Vec2[len];\n                for(int i = 0; i < len; i ++) out[i] = new Vec2(read.f(), read.f());\n                yield out;\n            }\n            case 19 -> new Vec2(read.f(), read.f());\n            case 20 -> Team.all[read.ub()];\n            case 21 -> readInts(read);\n            case 22 -> {\n                if(!allowArrays) throw new RuntimeException(\"Nested arrays are not allowed\");\n                int len = read.i();\n                if(len > maxArraySize) throw new RuntimeException(\"Invalid array size: \" + len);\n\n                Object[] objs = new Object[len];\n                for(int i = 0; i < len; i++){\n                    objs[i] = readObject(read, box, mapper, safe, false);\n                }\n                yield objs;","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/Anuken/Mindustry/blob/f695ad7e60323ebced984fa26d0bcf0bc54296b4/core/src/mindustry/io/TypeIO.java#L230-L266","documentation":"TypeIO.readObject() reads a Vec2[] (type 18). It reads a 2-byte (short) length and rejects it if it exceeds maxArraySize (1000, or 200 in the build-plan/safe=false path). The guard bounds memory use against a crafted packet.","triggerScenarios":"A type-18 packet whose short length field exceeds maxArraySize.","commonSituations":"Malicious/fuzzed client; a mod serializing a Vec2[] beyond the cap; the build-plan path where the limit is 200.","solutions":["Cap Vec2[] length to <= 1000 (<= 200 via build-plan config) on the write side.","Server-side: catch the RuntimeException and disconnect the sender."],"exampleFix":"// before\nwriteObject(write, hugeVec2Array);\n\n// after\nVec2[] trimmed = Arrays.copyOf(hugeVec2Array, Math.min(hugeVec2Array.length, 1000));\nwriteObject(write, trimmed);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    Object obj = TypeIO.readObject(read);\n} catch(RuntimeException e) {\n    Log.err(\"Malformed Vec2[] packet\", e);\n    con.kick(\"Invalid packet data.\");\n}","preventionTips":["Keep Vec2[] within 1000 elements (200 for build-plan config) before writeObject.","Server: treat the throw as hostile input and kick the sender."],"tags":["network","deserialization","array-size","security"],"backgroundTag":null,"analyzedSha":"f695ad7e60323ebced984fa26d0bcf0bc54296b4","analyzedAt":"2026-08-14T04:31:16.262Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}