avm2: Fix handling of default domain memory (#12308)

This commit is contained in:
Aaron Hill 2023-07-26 14:26:26 -04:00 committed by GitHub
parent 55906c22fa
commit 99ed2c6d4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 303 additions and 195 deletions

View File

@ -12,6 +12,7 @@ use gc_arena::{Collect, GcCell, MutationContext};
use ruffle_wstr::WStr;
use super::class::Class;
use super::error::error;
use super::string::AvmString;
/// Represents a set of scripts and movies that share traits across different
@ -40,8 +41,12 @@ struct DomainData<'gc> {
/// player globals setup (we need a global domain to put globals into, but
/// that domain needs the bytearray global)
pub domain_memory: Option<ByteArrayObject<'gc>>,
pub default_domain_memory: Option<ByteArrayObject<'gc>>,
}
const MIN_DOMAIN_MEMORY_LENGTH: usize = 1024;
impl<'gc> Domain<'gc> {
/// Create a new domain with no parent.
///
@ -62,6 +67,7 @@ impl<'gc> Domain<'gc> {
classes: PropertyMap::new(),
parent,
domain_memory: None,
default_domain_memory: None,
},
))
}
@ -82,6 +88,7 @@ impl<'gc> Domain<'gc> {
classes: PropertyMap::new(),
parent: Some(parent),
domain_memory: None,
default_domain_memory: None,
},
));
@ -294,6 +301,15 @@ impl<'gc> Domain<'gc> {
self.0.write(mc).classes.insert(class.read().name(), class);
}
pub fn is_default_domain_memory(&self) -> bool {
let read = self.0.read();
read.domain_memory.expect("Missing domain memory").as_ptr()
== read
.default_domain_memory
.expect("Missing default domain memory")
.as_ptr()
}
pub fn domain_memory(&self) -> ByteArrayObject<'gc> {
self.0
.read()
@ -303,10 +319,26 @@ impl<'gc> Domain<'gc> {
pub fn set_domain_memory(
&self,
mc: MutationContext<'gc, '_>,
domain_memory: ByteArrayObject<'gc>,
) {
self.0.write(mc).domain_memory = Some(domain_memory)
activation: &mut Activation<'_, 'gc>,
domain_memory: Option<ByteArrayObject<'gc>>,
) -> Result<(), Error<'gc>> {
let mut write = self.0.write(activation.context.gc_context);
let memory = if let Some(domain_memory) = domain_memory {
if domain_memory.storage().len() < MIN_DOMAIN_MEMORY_LENGTH {
return Err(Error::AvmError(error(
activation,
"Error #1504: End of file.",
1504,
)?));
}
domain_memory
} else {
write
.default_domain_memory
.expect("Default domain memory not initialized")
};
write.domain_memory = Some(memory);
Ok(())
}
/// Allocate the default domain memory for this domain, if it does not
@ -325,12 +357,23 @@ impl<'gc> Domain<'gc> {
domain_memory
.as_bytearray_mut(activation.context.gc_context)
.unwrap()
.set_length(1024);
.set_length(MIN_DOMAIN_MEMORY_LENGTH);
let mut write = self.0.write(activation.context.gc_context);
write
.domain_memory
.get_or_insert(domain_memory.as_bytearray_object().unwrap());
assert!(
write.domain_memory.is_none(),
"Already initialized domain memory!"
);
assert!(
write.default_domain_memory.is_none(),
"Already initialized domain memory!"
);
let bytearray = domain_memory.as_bytearray_object().unwrap();
write.domain_memory = Some(bytearray);
write.default_domain_memory = Some(bytearray);
Ok(())
}

View File

@ -19,5 +19,10 @@ package flash.system {
public native function hasDefinition(name:String):Boolean;
public native function getQualifiedDefinitionNames():Vector.<String>;
public static function get MIN_DOMAIN_MEMORY_LENGTH():uint {
return 1024;
}
}
}

View File

@ -140,11 +140,12 @@ pub fn set_domain_memory<'gc>(
this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(Value::Object(arg)) = args.get(0) {
if let Some(bytearray_obj) = arg.as_bytearray_object() {
if let Some(appdomain) = this.as_application_domain() {
appdomain.set_domain_memory(activation.context.gc_context, bytearray_obj);
}
if let Some(appdomain) = this.as_application_domain() {
let obj = args.try_get_object(activation, 0);
if let Some(obj) = obj {
appdomain.set_domain_memory(activation, Some(obj.as_bytearray_object().unwrap()))?;
} else {
appdomain.set_domain_memory(activation, None)?;
}
}
@ -158,8 +159,12 @@ pub fn get_domain_memory<'gc>(
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(appdomain) = this.as_application_domain() {
let bytearray_object: Object<'gc> = appdomain.domain_memory().into();
return Ok(bytearray_object.into());
if appdomain.is_default_domain_memory() {
return Ok(Value::Null);
} else {
let bytearray_object: Object<'gc> = appdomain.domain_memory().into();
return Ok(bytearray_object.into());
}
}
Ok(Value::Undefined)

View File

@ -0,0 +1,218 @@
package {
import flash.utils.Endian;
import avm2.intrinsics.memory.si8;
import avm2.intrinsics.memory.si16;
import avm2.intrinsics.memory.si32;
import avm2.intrinsics.memory.sf32;
import avm2.intrinsics.memory.sf64;
import avm2.intrinsics.memory.li8;
import avm2.intrinsics.memory.li16;
import avm2.intrinsics.memory.li32;
import avm2.intrinsics.memory.lf32;
import avm2.intrinsics.memory.lf64;
import avm2.intrinsics.memory.sxi1;
import avm2.intrinsics.memory.sxi8;
import avm2.intrinsics.memory.sxi16;
import flash.system.ApplicationDomain;
import flash.utils.ByteArray;
import flash.display.Sprite;
public class Test extends Sprite {
public function Test() {
init();
}
private function init():void {
trace("// ApplicationDomain.currentDomain.domainMemory");
trace(ApplicationDomain.currentDomain.domainMemory);
si8(65, 0);
trace("// ApplicationDomain.currentDomain.domainMemory after si8(65, 0)");
trace(ApplicationDomain.currentDomain.domainMemory);
trace("// li8(0) after si8(65, 0)");
trace(li8(0));
trace("// ApplicationDomain.currentDomain.domainMemory after li8(0)");
trace(ApplicationDomain.currentDomain.domainMemory);
si8(255, 0);
trace("// li8(0) after si8(255, 0)");
trace(li8(0));
si8(0xFFFFFFFF, 0);
trace("// li8(0) after si8(0xFFFFFFFF, 0)");
trace(li8(0));
trace("// li8(1) after si8(0xFFFFFFFF, 0)");
trace(li8(1));
trace("// li8(1) after si8(0xFFFFFFFF, 0)");
trace(li8(2));
trace("// li8(1) after si8(0xFFFFFFFF, 0)");
trace(li8(3));
si16(256, 0);
trace("// li8(0) after si16(256, 0)");
trace(li8(0));
trace("// li8(1) after si16(256, 0)");
trace(li8(1));
trace("// li16(0) after si16(256, 0)");
trace(li16(0));
si16(0xFFFF, 0);
trace("// li8(0) after si16(0xFFFF, 0)");
trace(li8(0));
trace("// li8(1) after si16(0xFFFF, 0)");
trace(li8(1));
trace("// li16(0) after si16(0xFFFF, 0)");
trace(li16(0));
si16(0xFFFFFFFF, 0);
trace("// li8(0) after si16(0xFFFFFFFF, 0)");
trace(li8(0));
trace("// li8(1) after si16(0xFFFFFFFF, 0)");
trace(li8(1));
trace("// li8(1) after si16(0xFFFFFFFF, 0)");
trace(li8(2));
trace("// li8(1) after si16(0xFFFFFFFF, 0)");
trace(li8(3));
si32(0xFFFFFFFF, 0);
trace("// li8(0) after si32(0xFFFFFFFF, 0)");
trace(li8(0));
trace("// li8(1) after si32(0xFFFFFFFF, 0)");
trace(li8(1));
trace("// li8(2) after si32(0xFFFFFFFF, 0)");
trace(li8(2));
trace("// li8(3) after si32(0xFFFFFFFF, 0)");
trace(li8(3));
trace("// li32(0) after si32(0xFFFFFFFF, 0)");
trace(li32(0));
sf32(0xFFFFFFFF, 0);
trace("// li8(0) after sf32(0xFFFFFFFF, 0)");
trace(li8(0));
trace("// li8(1) after sf32(0xFFFFFFFF, 0)");
trace(li8(1));
trace("// li8(2) after sf32(0xFFFFFFFF, 0)");
trace(li8(2));
trace("// li8(3) after sf32(0xFFFFFFFF, 0)");
trace(li8(3));
trace("// li32(0) after sf32(0xFFFFFFFF, 0)");
trace(li32(0));
trace("// lf32(0) after sf32(0xFFFFFFFF, 0)");
trace(lf32(0));
sf32(1234.7654321, 0);
trace("// li8(0) after sf32(1234.7654321, 0)");
trace(li8(0));
trace("// li8(1) after sf32(1234.7654321, 0)");
trace(li8(1));
trace("// li8(2) after sf32(1234.7654321, 0)");
trace(li8(2));
trace("// li8(3) after sf32(1234.7654321, 0)");
trace(li8(3));
trace("// li32(0) after sf32(1234.7654321, 0)");
trace(li32(0));
trace("// lf32(0) after sf32(1234.7654321, 0)");
trace(lf32(0));
sf64(999999.9999999999, 0);
trace("// li8(0) after sf64(999999.9999999999, 0)");
trace(li8(0));
trace("// li8(1) after sf64(999999.9999999999, 0)");
trace(li8(1));
trace("// li8(2) after sf64(999999.9999999999, 0)");
trace(li8(2));
trace("// li8(3) after sf64(999999.9999999999, 0)");
trace(li8(3));
trace("// li8(4) after sf64(999999.9999999999, 0)");
trace(li8(4));
trace("// li8(5) after sf64(999999.9999999999, 0)");
trace(li8(5));
trace("// li8(6) after sf64(999999.9999999999, 0)");
trace(li8(6));
trace("// li8(7) after sf64(999999.9999999999, 0)");
trace(li8(7));
trace("// li32(0) after sf64(999999.9999999999, 0)");
trace(li32(0));
trace("// li32(4) after sf64(999999.9999999999, 0)");
trace(li32(4));
trace("// lf32(0) after sf64(999999.9999999999, 0)");
trace(lf32(0));
trace("// lf32(4) after sf64(999999.9999999999, 0)");
trace(lf32(0));
trace("// lf64(0) after sf64(999999.9999999999, 0)");
trace(lf64(0));
trace("// sxi1(0)");
trace(sxi1(0));
trace("// sxi1(1)");
trace(sxi1(1));
trace("// sxi1(10)");
trace(sxi1(10));
trace("// sxi1(255)");
trace(sxi1(255));
trace("// sxi8(0)");
trace(sxi8(0));
trace("// sxi8(1)");
trace(sxi8(1));
trace("// sxi8(10)");
trace(sxi8(10));
trace("// sxi8(255)");
trace(sxi8(255));
trace("// sxi16(0)");
trace(sxi16(0));
trace("// sxi16(1)");
trace(sxi16(1));
trace("// sxi16(10)");
trace(sxi16(10));
trace("// sxi16(255)");
trace(sxi16(255));
trace("// si8(42, 0)");
si8(42, 0);
var bytes = new ByteArray();
bytes.length = 1024;
trace("// ApplicationDomain.currentDomain.domainMemory = bytes");
ApplicationDomain.currentDomain.domainMemory = bytes;
trace("// li8(0) after explicit overwrite");
trace(li8(0));
trace("// si8(45, 0)");
si8(45, 0);
trace("// ApplicationDomain.currentDomain.domainMemory = null");
ApplicationDomain.currentDomain.domainMemory = null;
trace("// li8(0)");
trace(li8(0));
trace("// ApplicationDomain.MIN_DOMAIN_MEMORY_LENGTH")
trace(ApplicationDomain.MIN_DOMAIN_MEMORY_LENGTH)
var bytes = new ByteArray();
bytes.length = ApplicationDomain.MIN_DOMAIN_MEMORY_LENGTH - 1;
try {
ApplicationDomain.currentDomain.domainMemory = bytes;
trace("FAILED - write should have thrown an error")
} catch (e) {
trace("Caught error: " + e);
}
}
}
}

View File

@ -1,5 +1,11 @@
// ApplicationDomain.currentDomain.domainMemory
null
// ApplicationDomain.currentDomain.domainMemory after si8(65, 0)
null
// li8(0) after si8(65, 0)
65
// ApplicationDomain.currentDomain.domainMemory after li8(0)
null
// li8(0) after si8(255, 0)
255
// li8(0) after si8(0xFFFFFFFF, 0)
@ -114,3 +120,14 @@ NaN
10
// sxi16(255)
255
// si8(42, 0)
// ApplicationDomain.currentDomain.domainMemory = bytes
// li8(0) after explicit overwrite
0
// si8(45, 0)
// ApplicationDomain.currentDomain.domainMemory = null
// li8(0)
42
// ApplicationDomain.MIN_DOMAIN_MEMORY_LENGTH
1024
Caught error: Error: Error #1504: End of file.

View File

@ -1,180 +0,0 @@
package
{
import flash.utils.Endian;
import avm2.intrinsics.memory.si8;
import avm2.intrinsics.memory.si16;
import avm2.intrinsics.memory.si32;
import avm2.intrinsics.memory.sf32;
import avm2.intrinsics.memory.sf64;
import avm2.intrinsics.memory.li8;
import avm2.intrinsics.memory.li16;
import avm2.intrinsics.memory.li32;
import avm2.intrinsics.memory.lf32;
import avm2.intrinsics.memory.lf64;
import avm2.intrinsics.memory.sxi1;
import avm2.intrinsics.memory.sxi8;
import avm2.intrinsics.memory.sxi16;
import flash.system.ApplicationDomain;
import flash.utils.ByteArray;
import flash.display.Sprite;
public class Test extends Sprite
{
public function Test()
{
init();
}
private function init(): void
{
si8(65, 0);
trace("// li8(0) after si8(65, 0)");
trace(li8(0));
si8(255, 0);
trace("// li8(0) after si8(255, 0)");
trace(li8(0));
si8(0xFFFFFFFF, 0);
trace("// li8(0) after si8(0xFFFFFFFF, 0)");
trace(li8(0));
trace("// li8(1) after si8(0xFFFFFFFF, 0)");
trace(li8(1));
trace("// li8(1) after si8(0xFFFFFFFF, 0)");
trace(li8(2));
trace("// li8(1) after si8(0xFFFFFFFF, 0)");
trace(li8(3));
si16(256, 0);
trace("// li8(0) after si16(256, 0)");
trace(li8(0));
trace("// li8(1) after si16(256, 0)");
trace(li8(1));
trace("// li16(0) after si16(256, 0)");
trace(li16(0));
si16(0xFFFF, 0);
trace("// li8(0) after si16(0xFFFF, 0)");
trace(li8(0));
trace("// li8(1) after si16(0xFFFF, 0)");
trace(li8(1));
trace("// li16(0) after si16(0xFFFF, 0)");
trace(li16(0));
si16(0xFFFFFFFF, 0);
trace("// li8(0) after si16(0xFFFFFFFF, 0)");
trace(li8(0));
trace("// li8(1) after si16(0xFFFFFFFF, 0)");
trace(li8(1));
trace("// li8(1) after si16(0xFFFFFFFF, 0)");
trace(li8(2));
trace("// li8(1) after si16(0xFFFFFFFF, 0)");
trace(li8(3));
si32(0xFFFFFFFF, 0);
trace("// li8(0) after si32(0xFFFFFFFF, 0)");
trace(li8(0));
trace("// li8(1) after si32(0xFFFFFFFF, 0)");
trace(li8(1));
trace("// li8(2) after si32(0xFFFFFFFF, 0)");
trace(li8(2));
trace("// li8(3) after si32(0xFFFFFFFF, 0)");
trace(li8(3));
trace("// li32(0) after si32(0xFFFFFFFF, 0)");
trace(li32(0));
sf32(0xFFFFFFFF, 0);
trace("// li8(0) after sf32(0xFFFFFFFF, 0)");
trace(li8(0));
trace("// li8(1) after sf32(0xFFFFFFFF, 0)");
trace(li8(1));
trace("// li8(2) after sf32(0xFFFFFFFF, 0)");
trace(li8(2));
trace("// li8(3) after sf32(0xFFFFFFFF, 0)");
trace(li8(3));
trace("// li32(0) after sf32(0xFFFFFFFF, 0)");
trace(li32(0));
trace("// lf32(0) after sf32(0xFFFFFFFF, 0)");
trace(lf32(0));
sf32(1234.7654321, 0);
trace("// li8(0) after sf32(1234.7654321, 0)");
trace(li8(0));
trace("// li8(1) after sf32(1234.7654321, 0)");
trace(li8(1));
trace("// li8(2) after sf32(1234.7654321, 0)");
trace(li8(2));
trace("// li8(3) after sf32(1234.7654321, 0)");
trace(li8(3));
trace("// li32(0) after sf32(1234.7654321, 0)");
trace(li32(0));
trace("// lf32(0) after sf32(1234.7654321, 0)");
trace(lf32(0));
sf64(999999.9999999999, 0);
trace("// li8(0) after sf64(999999.9999999999, 0)");
trace(li8(0));
trace("// li8(1) after sf64(999999.9999999999, 0)");
trace(li8(1));
trace("// li8(2) after sf64(999999.9999999999, 0)");
trace(li8(2));
trace("// li8(3) after sf64(999999.9999999999, 0)");
trace(li8(3));
trace("// li8(4) after sf64(999999.9999999999, 0)");
trace(li8(4));
trace("// li8(5) after sf64(999999.9999999999, 0)");
trace(li8(5));
trace("// li8(6) after sf64(999999.9999999999, 0)");
trace(li8(6));
trace("// li8(7) after sf64(999999.9999999999, 0)");
trace(li8(7));
trace("// li32(0) after sf64(999999.9999999999, 0)");
trace(li32(0));
trace("// li32(4) after sf64(999999.9999999999, 0)");
trace(li32(4));
trace("// lf32(0) after sf64(999999.9999999999, 0)");
trace(lf32(0));
trace("// lf32(4) after sf64(999999.9999999999, 0)");
trace(lf32(0));
trace("// lf64(0) after sf64(999999.9999999999, 0)");
trace(lf64(0));
trace("// sxi1(0)");
trace(sxi1(0));
trace("// sxi1(1)");
trace(sxi1(1));
trace("// sxi1(10)");
trace(sxi1(10));
trace("// sxi1(255)");
trace(sxi1(255));
trace("// sxi8(0)");
trace(sxi8(0));
trace("// sxi8(1)");
trace(sxi8(1));
trace("// sxi8(10)");
trace(sxi8(10));
trace("// sxi8(255)");
trace(sxi8(255));
trace("// sxi16(0)");
trace(sxi16(0));
trace("// sxi16(1)");
trace(sxi16(1));
trace("// sxi16(10)");
trace(sxi16(10));
trace("// sxi16(255)");
trace(sxi16(255));
}
}
}