Skip to content

SWF AVM Specification Errata

Daniel Jacobs edited this page Apr 7, 2022 · 19 revisions

This page lists errata and undocumented information from the official Flash specifications provided by Adobe:

(TODO: Jot down anything I vaguely remember being incorrect)

SWF19

DefineFunction2

If a function is running on the root timeline, _parent is undefined and does not get preloaded into a register. Instead, _global mistakenly uses the same register.

This means that this code will be incorrect when placed on the root timeline:

function f()
{
	trace(_parent);  // traces _global
	trace(_global);  // trace undefined
}
f();

See the define_function2_preload_order test for an example.

This doesn't seem to apply to other preloaded registers like super. If super is undefined, it still gets set to a register.

Double-precision floats

(SWF19 p.16)

Double-precision floats in AVM1 ActionPush actions are not stored as 64-bit little endian, but instead stored as two 32-bit little endian chunks. This requires some byte swapping to reconstruct the double. This is the order of the bytes in the SWF file: 45670123

Or this code which swaps it into proper 64-bit little endian:

let num: [u8; 4];
num.swap(0, 4);
num.swap(1, 5);
num.swap(2, 6);
num.swap(3, 7);
(&num[..]).read_f64::<LittleEndian>()

Note that this only applies to AVM1; doubles in AVM2 are standard little-endian.

DebugId tag

Undocumented tag generated in debug builds. See http://wahlers.com.br/claus/blog/undocumented-swf-tags-written-by-mxmlc/ for more info.

Data Size
Unknown UI8[16]

DefineButtonCxform tag

(SWF19 p.199)

This tag was only used briefly in Flash 2(?) and is not well documented (TODO: Is there any content in the wild that uses this?)

The tag can actually contain multiple color transforms. It applies the color transforms respectively to each character record in the define button tag.

PlaceObject3

(SWF19 pp.48-52)

The spec says that ClassName will be present if (HasClassName || (HasImage && HasCharacterId)), but it should actually be (HasClassName || (HasImage && !HasCharacterId)). That is, if we are placing an image without a character ID, we need a class name to know which image to create.

ProductInfo tag

Undocumented ID of the software that published the SWF. See http://wahlers.com.br/claus/blog/undocumented-swf-tags-written-by-mxmlc/ for more info.

Data Size
ProductId U32
Edition U32
MajorVersion U8
MinorVersion U8
BuildNumber U64
CompileDate U64

Protect tag

(SWF19 p.53)

If the Protect tag has an MD5 hash, there will be two bytes of data before the MD5 (they seem to always be 0?) Tag format:

Data Size
Unknown U16
MD5 STRING

ActionDelete2

(SWF19 p.94)

ActionDelete2 push true or false based on if the property actually existed prior to deletion.

ActionGetURL2

(SWF19 pp.82-83)

The SendVarsFlag, LoadTargetFlag, and LoadVariablesFlags are listed in reverse order. This is the proper order:

LoadVariablesFlag  UB[1]
LoadTargetFlag     UB[1]
Reserved           UB[4]
SendVarsFlag       UB[2]

AVM2

Variable-length encoding and s32

(AVM2 p.18)

When reading an variable-length encoded s32, no sign-extension is done. The value is read as a variable-length u32 and reinterpreted as signed. This means that any negative integer must takes up the full 5 bytes.

0b0100_0000 as an s32 is 64, not as -64.

0b1000_0000 0b0100_0000 as an s32 is 8192, not as -8192.

0b1000_0000 0b1000_0000 0b1000_0000 0b1000_0000 0b0000_1000 is -2147483648.