avm1: Prevent panic when close is called in event handler

Also adds a test case for this.
This commit is contained in:
sleepycatcoding 2023-08-04 12:12:49 +03:00 committed by Nathan Adams
parent 82c57a0d97
commit aac1931569
6 changed files with 54 additions and 2 deletions

View File

@ -321,10 +321,13 @@ impl<'gc> Sockets<'gc> {
let xml_socket = let xml_socket =
XmlSocket::cast(target.into()).expect("target should be XmlSocket"); XmlSocket::cast(target.into()).expect("target should be XmlSocket");
// Get XmlSocket read buffer.
let mut buffer = xml_socket.read_buffer(); let mut buffer = xml_socket.read_buffer();
buffer.extend(data); buffer.extend(data);
// Check for a message. let mut messages = vec![];
// Check for messages.
while let Some((index, _)) = while let Some((index, _)) =
buffer.iter().enumerate().find(|(_, &b)| b == 0) buffer.iter().enumerate().find(|(_, &b)| b == 0)
{ {
@ -332,8 +335,14 @@ impl<'gc> Sockets<'gc> {
// Remove null byte. // Remove null byte.
let _ = buffer.drain(..1); let _ = buffer.drain(..1);
let message = AvmString::new_utf8_bytes(activation.gc(), &message); // Store the message in cache.
messages.push(AvmString::new_utf8_bytes(activation.gc(), &message));
}
// Drop the reference to the buffer, to make sure the SWF can call with close.
drop(buffer);
for message in messages {
let _ = target.call_method( let _ = target.call_method(
"onData".into(), "onData".into(),
&[message.into()], &[message.into()],

View File

@ -0,0 +1,6 @@
connected
true
data:
Hello!
Closing socket in onData handler
Successfully closed socket

View File

@ -0,0 +1,13 @@
[
{
"type": "Send",
"payload": [ 72, 101, 108, 108, 111, 33, 0 ]
},
{
"type": "Send",
"payload": [ 60, 114, 111, 111, 116, 62, 60, 105, 116, 101, 109, 32, 47, 62, 60, 47, 114, 111, 111, 116, 62, 0 ]
},
{
"type": "WaitForDisconnect"
}
]

View File

@ -0,0 +1,23 @@
class Test {
static function main() {
var socket = new XMLSocket();
socket.onConnect = function (status:Boolean) {
trace("connected");
trace(status);
};
socket.onData = function (data:String) {
trace("data:")
trace(data);
trace("Closing socket in onData handler");
socket.close();
trace("Successfully closed socket");
};
socket.onClose = function () {
trace("closed");
};
socket.connect("localhost", 8001);
}
}

View File

@ -0,0 +1 @@
num_ticks = 10