TooTallNate / Java-WebSocket

A barebones WebSocket client and server implementation written in 100% Java.
http://tootallnate.github.io/Java-WebSocket
MIT License
10.47k stars 2.57k forks source link

Server Crashes with a large payload #1436

Closed RedTeaDev closed 1 month ago

RedTeaDev commented 1 month ago

Describe the bug The server crashes for OOM when receiving a large TEXT frames

To Reproduce Steps to reproduce the behavior:

  1. Send a large amount of data to the server, for example send("{" + "a".repeat(Integer.MAX_VALUE - 1024) + ":'test'}");
  2. Check logs
  3. Server crashs

Example application to reproduce the issue I have used ChatServer.java and was able to reproduce this issue by doing send("a".repeat(Integer.MAX_VALUE - 1024), null)); from client on WebSocketClient#onOpen, though, any clients should be able to reproduct this issue

Expected behavior

Should disconnect the client and continue

Debug log The the debug log (set the log level to TRACE) to help explain your problem.

latest.log

[2024-08-01T19:10:30,585 ERROR] WebSocketWorker-37: o.j.WebSocketImpl - Got fatal error during frame processing
[2024-08-01T19:10:30,585 ERROR] WebSocketWorker-37: o.j.s.WebSocketServer - Got fatal error in worker thread WebSocketWorker-37
[2024-08-01T19:10:30,585 ERROR] WebSocketWorker-37: o.j.s.WebSocketServer - Shutdown due to fatal error
java.lang.Exception: java.lang.OutOfMemoryError: Required array length 2147482624 + 1024 is too large
    at org.java_websocket.server.WebSocketServer$WebSocketWorker.run(WebSocketServer.java:1113) [Java-WebSocket-1.5.7.jar:?]
Caused by: java.lang.OutOfMemoryError: Required array length 2147482624 + 1024 is too large
    at java.base/jdk.internal.util.ArraysSupport.hugeLength(ArraysSupport.java:752) ~[?:?]
    at java.base/jdk.internal.util.ArraysSupport.newLength(ArraysSupport.java:745) ~[?:?]
    at java.base/java.nio.charset.CharsetDecoder.decode(CharsetDecoder.java:829) ~[?:?]
    at org.java_websocket.util.Charsetfunctions.stringUtf8(Charsetfunctions.java:79) ~[Java-WebSocket-1.5.7.jar:?]
    at org.java_websocket.drafts.Draft_6455.processFrameText(Draft_6455.java:986) ~[Java-WebSocket-1.5.7.jar:?]
    at org.java_websocket.drafts.Draft_6455.processFrame(Draft_6455.java:910) ~[Java-WebSocket-1.5.7.jar:?]
    at org.java_websocket.WebSocketImpl.decodeFrames(WebSocketImpl.java:397) ~[Java-WebSocket-1.5.7.jar:?]
    at org.java_websocket.WebSocketImpl.decode(WebSocketImpl.java:229) ~[Java-WebSocket-1.5.7.jar:?]
    at org.java_websocket.server.WebSocketServer$WebSocketWorker.doDecode(WebSocketServer.java:1134) ~[Java-WebSocket-1.5.7.jar:?]
    at org.java_websocket.server.WebSocketServer$WebSocketWorker.run(WebSocketServer.java:1106) ~[Java-WebSocket-1.5.7.jar:?]
[2024-08-01T19:10:30,593 DEBUG] WebSocketWorker-37: d.r.s.s.ServerImpl - Closing connection from /127.0.0.1:62695 due to internal error
[2024-08-01T19:10:30,594 ERROR] WebSocketWorker-37: d.r.s.s.ServerImpl - java.lang.Exception: java.lang.OutOfMemoryError: Required array length 2147482624 + 1024 is too large

Environment(please complete the following information):

Additional context Add any other context about the problem here.

interestingly, server did not crash when the data is not a JSON, but it crashes when i pass thing likes {"a":"<large amont of junk data>"}

Here is the python script i used to generate the payload:

from websockets.sync.client import connect

with connect("ws://localhost:8887") as websocket:
        websocket.send("{'" + "a" * (2147483647 - 512) + "':'test'}")
        message = websocket.recv()
        print(f"Received: {message}")

Shutdown due to fatal error java.lang.Exception: java.lang.OutOfMemoryError: Required array length 2147483136 + 1024 is too large

When i passes random junk data it didn't crash, only crashes when i try to send "JSON" data.

Update: adding a OOM check on Charsetfunctions#stringUtf8 seems to fix the issue. image

marci4 commented 1 month ago

Hello @RedTeaDev, have you tried setting the maximum frame size (https://github.com/TooTallNate/Java-WebSocket/blob/master/src/main/java/org/java_websocket/drafts/Draft_6455.java#L237)

Best regards, Marcel

RedTeaDev commented 1 month ago

Thanks, it fixed the issue by closing the connection!

However shouldn't a maximum frame size be applied as a default value to the draft?