{"record":{"id":"c23c91602b1b058b","repo":"dotnet/aspnetcore","slug":"messages-over-2gb-in-size-are-not-supported","errorCode":null,"errorMessage":"Messages over 2GB in size are not supported","messagePattern":"Messages over 2GB in size are not supported","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/SignalR/clients/java/signalr/messagepack/src/main/java/com/microsoft/signalr/messagepack/Utils.java","lineNumber":45,"sourceCode":"        int length = 0;\n        int numBytes = 0;\n        int maxLength = 5;\n        byte curr;\n        \n        do {\n            // If we run out of bytes before we finish reading the length header, the message is malformed\n            if (buffer.hasRemaining()) {\n                curr = buffer.get();\n            } else {\n                throw new RuntimeException(\"The length header was incomplete\");\n            }\n            length = length | (curr & (byte) 0x7f) << (numBytes * 7);\n            numBytes++;\n        } while (numBytes < maxLength && (curr & (byte) 0x80) != 0);\n        \n        // Max header length is 5, and the maximum value of the 5th byte is 0x07\n        if ((curr & (byte) 0x80) != 0 || (numBytes == maxLength && curr > (byte) 0x07)) {\n            throw new RuntimeException(\"Messages over 2GB in size are not supported\");\n        }\n        \n        return length;\n    }\n    \n    public static ArrayList<Byte> getLengthHeader(int length) {\n        // This code writes length prefix of the message as a VarInt. Read the comment in\n        // the readLengthHeader for details.\n        \n        ArrayList<Byte> header = new ArrayList<Byte>();\n        do {\n            byte curr = (byte) (length & 0x7f);\n            length >>= 7;\n            if (length > 0) {\n                curr |= 0x80;\n            }\n            header.add(curr);\n        } while (length > 0);","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/SignalR/clients/java/signalr/messagepack/src/main/java/com/microsoft/signalr/messagepack/Utils.java#L27-L63","documentation":"readLengthHeader caps the supported payload size at 2 GB (Integer.MAX_VALUE, 0x7FFFFFFF). After reading up to 5 VarInt bytes, if the continuation bit is still set or the 5th byte exceeds 0x07, the decoded length would overflow a signed int, so the frame is rejected.","triggerScenarios":"The VarInt length prefix decodes to a value larger than 2 GiB, either because the payload genuinely exceeds that size or - far more commonly - because the length bytes are corrupt and decode to a huge number (Utils.java:43-46).","commonSituations":"Corrupted framing where random bytes with the high bit set are interpreted as a multi-byte length; a peer injecting garbage; rarely, an attempt to send a legitimately enormous payload.","solutions":["Treat as a malformed/fatal frame: drop the connection and reconnect.","If you actually stream large data, chunk it through SignalR streaming (StreamItem) instead of one huge message.","Add an inbound size cap before invoking readLengthHeader to reject absurd values early."],"exampleFix":"// before - parse untrusted buffer directly\nint len = Utils.readLengthHeader(buffer);\n// after - sanity-cap first\nint len = Utils.readLengthHeader(buffer);\nif (len < 0 || len > MAX_ALLOWED) throw new IOException(\"Frame too large: \" + len);","handlingStrategy":"validation","validationCode":"final int MAX_FRAME = 64 * 1024 * 1024; // pick a sane cap\nint len = Utils.readLengthHeader(buffer);\nif (len < 0 || len > MAX_FRAME) {\n    throw new java.io.IOException(\"Rejecting oversize/corrupt frame length: \" + len);\n}","typeGuard":"static boolean isPlausibleLength(int len) {\n    return len >= 0 && len <= MAX_FRAME;\n}","tryCatchPattern":"try {\n    int len = Utils.readLengthHeader(buffer);\n} catch (RuntimeException ex) {\n    if (ex.getMessage().contains(\"over 2GB\")) {\n        // corrupt length header or malicious input - drop connection\n        connection.dispose();\n    }\n    throw ex;\n}","preventionTips":["Apply an inbound frame-size cap before reading the length header.","Stream large payloads via SignalR streaming instead of one giant message.","Treat a 2GB-length error as corrupt framing, not a real payload."],"tags":["java","signalr","messagepack","framing","limits"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}