Fixed: AS1/2 actions must use SWF charset when writing its length

This commit is contained in:
Jindra Petřík
2025-08-19 18:14:41 +02:00
parent a84cdd3682
commit 1c88c0304b
9 changed files with 27 additions and 13 deletions

View File

@@ -145,7 +145,7 @@ public abstract class Action implements GraphSourceItem {
/**
* Charset - SWFs version 5 and lower do not use UTF-8
*/
private String charset;
protected String charset;
/**
* Names of ActionScript properties
@@ -538,7 +538,7 @@ public abstract class Action implements GraphSourceItem {
ActionConstantPool cPool = (ActionConstantPool) action;
List<String> constantPool = constantPools.get(poolIdx);
int size = ActionConstantPool.calculateSize(constantPool);
int size = ActionConstantPool.calculateSize(constantPool, action.getCharset());
if (size > 0xffff && tryInline) {
for (int i = 0; i < constantPool.size(); i++) {
int refCount = actions.getConstantPoolIndexReferenceCount(i);
@@ -548,7 +548,7 @@ public abstract class Action implements GraphSourceItem {
}
}
size = ActionConstantPool.calculateSize(constantPool);
size = ActionConstantPool.calculateSize(constantPool, action.getCharset());
}
if (size > 0xffff) {

View File

@@ -2204,7 +2204,7 @@ public class ActionScript2Parser {
int index = constantPool.indexOf(s);
if (index == -1) {
if (ActionConstantPool.calculateSize(constantPool) + ActionConstantPool.calculateSize(s) <= 0xffff) {
if (ActionConstantPool.calculateSize(constantPool, charset) + ActionConstantPool.calculateSize(s, charset) <= 0xffff) {
// constant pool is not full
constantPool.add(s);
index = constantPool.indexOf(s);

View File

@@ -121,7 +121,7 @@ public class ActionGetURL extends Action {
*/
@Override
protected int getContentBytesLength() {
return Utf8Helper.getBytesLength(urlString) + Utf8Helper.getBytesLength(targetString) + 2;
return Utf8Helper.getBytesLength(urlString, charset) + Utf8Helper.getBytesLength(targetString, charset) + 2;
}
@Override

View File

@@ -98,7 +98,7 @@ public class ActionGoToLabel extends Action {
*/
@Override
protected int getContentBytesLength() {
return Utf8Helper.getBytesLength(label) + 1;
return Utf8Helper.getBytesLength(label, charset) + 1;
}
/**

View File

@@ -104,7 +104,7 @@ public class ActionSetTarget extends Action {
*/
@Override
protected int getContentBytesLength() {
return Utf8Helper.getBytesLength(targetName) + 1;
return Utf8Helper.getBytesLength(targetName, charset) + 1;
}
/**

View File

@@ -216,7 +216,7 @@ public class ActionPush extends Action {
int res = 0;
for (Object o : vals) {
if (o instanceof String) {
res += Utf8Helper.getBytesLength((String) o) + 2;
res += Utf8Helper.getBytesLength((String) o, charset) + 2;
} else if (o instanceof Float) {
res += 5;
} else if (o == Null.INSTANCE) {

View File

@@ -125,29 +125,31 @@ public class ActionConstantPool extends Action {
*/
@Override
protected int getContentBytesLength() {
return calculateSize(constantPool);
return calculateSize(constantPool, charset);
}
/**
* Calculates size of string converted to bytes
*
* @param str String
* @param charset Charset
* @return Size
*/
public static int calculateSize(String str) {
return Utf8Helper.getBytesLength(str) + 1;
public static int calculateSize(String str, String charset) {
return Utf8Helper.getBytesLength(str, charset) + 1;
}
/**
* Calculates the size of the action converted to bytes
*
* @param strings Strings
* @param charset Charset
* @return Size
*/
public static int calculateSize(List<String> strings) {
public static int calculateSize(List<String> strings, String charset) {
int res = 2;
for (String s : strings) {
res += Utf8Helper.getBytesLength(s) + 1;
res += Utf8Helper.getBytesLength(s, charset) + 1;
}
return res;

View File

@@ -152,6 +152,17 @@ public class Utf8Helper {
// todo: make it faster without actually writing it to an array
return getBytes(string).length;
}
public static int getBytesLength(String string, String charset) {
if (charset.toLowerCase().equals(charsetName)) {
return getBytesLength(string);
}
try {
return string.getBytes(charset).length;
} catch (UnsupportedEncodingException ex) {
return 0; //Should not happen
}
}
private static String escapeInvalidUtf8Char(int v) {
//Note: for writing the string "{invalid_utf8=xxx}" itself, you can escape it with "{+invalid_utf8=xxx}"