Remove SnakeYAML for manual YAML Parser (#3191)

* Simple straitforward yaml serialization with minimal needed functionality

* Consolidate ApkInfo tests in the package brut.androlib.apk, unify interface YamlReader and add ApkInfoSerializationTest read -> write -> read test

* remove dependencies from snakeyaml

* remove unused methods

* correct indent test value

* correct style with curly braces

* add test item with hieroglyph
This commit is contained in:
sv99
2023-07-29 12:59:15 +03:00
committed by GitHub
parent da6ed0f729
commit 62b9eedb9e
31 changed files with 1084 additions and 208 deletions

View File

@ -0,0 +1,132 @@
package brut.androlib.apk;
import brut.androlib.exceptions.AndrolibException;
import org.junit.Test;
import static org.junit.Assert.*;
public class ApkInfoReaderTest {
private void checkStandard(ApkInfo apkInfo) {
assertEquals("standard.apk", apkInfo.getApkFileName());
assertFalse(apkInfo.resourcesAreCompressed);
assertEquals(1, apkInfo.doNotCompress.size());
assertEquals("resources.arsc", apkInfo.doNotCompress.iterator().next());
assertFalse(apkInfo.isFrameworkApk);
assertNotNull(apkInfo.packageInfo);
assertEquals("127", apkInfo.packageInfo.forcedPackageId);
assertNull(apkInfo.packageInfo.renameManifestPackage);
assertNotNull(apkInfo.getSdkInfo());
assertEquals(2, apkInfo.getSdkInfo().size());
assertEquals("25", apkInfo.getSdkInfo().get("minSdkVersion"));
assertEquals("30", apkInfo.getSdkInfo().get("targetSdkVersion"));
assertFalse(apkInfo.sharedLibrary);
assertFalse(apkInfo.sparseResources);
assertNotNull(apkInfo.usesFramework);
assertNotNull(apkInfo.usesFramework.ids);
assertEquals(1, apkInfo.usesFramework.ids.size());
assertEquals(1, (long)apkInfo.usesFramework.ids.get(0));
assertNull(apkInfo.usesFramework.tag);
assertNotNull(apkInfo.versionInfo);
assertNull(apkInfo.versionInfo.versionCode);
assertNull(apkInfo.versionInfo.versionName);
}
@Test
public void testStandard() throws AndrolibException {
ApkInfo apkInfo = ApkInfo.load(
this.getClass().getResourceAsStream("/apk/standard.yml"));
checkStandard(apkInfo);
assertEquals("2.8.1", apkInfo.version);
}
@Test
public void testUnknownFields() throws AndrolibException {
ApkInfo apkInfo = ApkInfo.load(
this.getClass().getResourceAsStream("/apk/unknown_fields.yml"));
checkStandard(apkInfo);
assertEquals("2.8.1", apkInfo.version);
}
@Test
public void testSkipIncorrectIndent() throws AndrolibException {
ApkInfo apkInfo = ApkInfo.load(
this.getClass().getResourceAsStream("/apk/skip_incorrect_indent.yml"));
checkStandard(apkInfo);
assertNotEquals("2.0.0", apkInfo.version);
}
@Test
public void testFirstIncorrectIndent() throws AndrolibException {
ApkInfo apkInfo = ApkInfo.load(
this.getClass().getResourceAsStream("/apk/first_incorrect_indent.yml"));
checkStandard(apkInfo);
assertNotEquals("2.0.0", apkInfo.version);
}
@Test
public void testUnknownFiles() throws AndrolibException {
ApkInfo apkInfo = ApkInfo.load(
this.getClass().getResourceAsStream("/apk/unknown_files.yml"));
assertEquals("2.0.0", apkInfo.version);
assertEquals("testapp.apk", apkInfo.getApkFileName());
assertFalse(apkInfo.isFrameworkApk);
assertNotNull(apkInfo.usesFramework);
assertEquals(1, apkInfo.usesFramework.ids.size());
assertEquals(1, (long)apkInfo.usesFramework.ids.get(0));
assertNotNull(apkInfo.packageInfo);
assertEquals("127", apkInfo.packageInfo.forcedPackageId);
assertNotNull(apkInfo.versionInfo);
assertEquals("1", apkInfo.versionInfo.versionCode);
assertEquals("1.0", apkInfo.versionInfo.versionName);
assertFalse(apkInfo.resourcesAreCompressed);
assertNotNull(apkInfo.doNotCompress);
assertEquals(4, apkInfo.doNotCompress.size());
assertEquals("assets/0byte_file.jpg", apkInfo.doNotCompress.get(0));
assertEquals("arsc", apkInfo.doNotCompress.get(1));
assertEquals("png", apkInfo.doNotCompress.get(2));
assertEquals("mp3", apkInfo.doNotCompress.get(3));
assertNotNull(apkInfo.unknownFiles);
assertEquals(7, apkInfo.unknownFiles.size());
assertEquals("8", apkInfo.unknownFiles.get("AssetBundle/assets/a.txt"));
assertEquals("8", apkInfo.unknownFiles.get("AssetBundle/b.txt"));
assertEquals("8", apkInfo.unknownFiles.get("hidden.file"));
assertEquals("8", apkInfo.unknownFiles.get("non\u007Fprintable.file"));
assertEquals("0", apkInfo.unknownFiles.get("stored.file"));
assertEquals("8", apkInfo.unknownFiles.get("unk_folder/unknown_file"));
assertEquals("8", apkInfo.unknownFiles.get("lib_bug603/bug603"));
}
@Test
public void testUlist_with_indent() throws AndrolibException {
ApkInfo apkInfo = ApkInfo.load(
this.getClass().getResourceAsStream("/apk/list_with_indent.yml"));
assertEquals("2.8.0", apkInfo.version);
assertEquals("basic.apk", apkInfo.getApkFileName());
assertFalse(apkInfo.isFrameworkApk);
assertNotNull(apkInfo.usesFramework);
assertEquals(1, apkInfo.usesFramework.ids.size());
assertEquals(1, (long)apkInfo.usesFramework.ids.get(0));
assertEquals("tag", apkInfo.usesFramework.tag);
assertNotNull(apkInfo.packageInfo);
assertEquals("127", apkInfo.packageInfo.forcedPackageId);
assertEquals("com.test.basic", apkInfo.packageInfo.renameManifestPackage);
assertNotNull(apkInfo.getSdkInfo());
assertEquals(3, apkInfo.getSdkInfo().size());
assertEquals("4", apkInfo.getSdkInfo().get("minSdkVersion"));
assertEquals("30", apkInfo.getSdkInfo().get("maxSdkVersion"));
assertEquals("22", apkInfo.getSdkInfo().get("targetSdkVersion"));
assertFalse(apkInfo.sharedLibrary);
assertTrue(apkInfo.sparseResources);
assertNotNull(apkInfo.unknownFiles);
assertEquals(1, apkInfo.unknownFiles.size());
assertEquals("1", apkInfo.unknownFiles.get("hidden.file"));
assertNotNull(apkInfo.versionInfo);
assertEquals("71", apkInfo.versionInfo.versionCode);
assertEquals("1.0.70", apkInfo.versionInfo.versionName);
assertNotNull(apkInfo.doNotCompress);
assertEquals(2, apkInfo.doNotCompress.size());
assertEquals("resources.arsc", apkInfo.doNotCompress.get(0));
assertEquals("png", apkInfo.doNotCompress.get(1));
}
}

View File

@ -0,0 +1,79 @@
/*
* Copyright (C) 2010 Ryszard Wiśniewski <brut.alll@gmail.com>
* Copyright (C) 2010 Connor Tumbleson <connor.tumbleson@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package brut.androlib.apk;
import brut.androlib.exceptions.AndrolibException;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.io.*;
import static org.junit.Assert.*;
public class ApkInfoSerializationTest {
@Rule
public TemporaryFolder folder = new TemporaryFolder();
@Test
public void checkApkInfoSerialization() throws IOException, AndrolibException {
ApkInfo control = ApkInfo.load(
this.getClass().getResourceAsStream("/apk/unknown_files.yml"));
check(control);
File savedApkInfo = folder.newFile( "saved.yml" );
control.save(savedApkInfo);
try (
FileInputStream fis = new FileInputStream(savedApkInfo);
) {
ApkInfo saved = ApkInfo.load(fis);
check(saved);
}
}
private void check(ApkInfo apkInfo) {
assertEquals("2.0.0", apkInfo.version);
assertEquals("testapp.apk", apkInfo.getApkFileName());
assertFalse(apkInfo.isFrameworkApk);
assertNotNull(apkInfo.usesFramework);
assertEquals(1, apkInfo.usesFramework.ids.size());
assertEquals(1, (long)apkInfo.usesFramework.ids.get(0));
assertNotNull(apkInfo.packageInfo);
assertEquals("127", apkInfo.packageInfo.forcedPackageId);
assertNotNull(apkInfo.versionInfo);
assertEquals("1", apkInfo.versionInfo.versionCode);
assertEquals("1.0", apkInfo.versionInfo.versionName);
assertFalse(apkInfo.resourcesAreCompressed);
assertNotNull(apkInfo.doNotCompress);
assertEquals(4, apkInfo.doNotCompress.size());
assertEquals("assets/0byte_file.jpg", apkInfo.doNotCompress.get(0));
assertEquals("arsc", apkInfo.doNotCompress.get(1));
assertEquals("png", apkInfo.doNotCompress.get(2));
assertEquals("mp3", apkInfo.doNotCompress.get(3));
assertNotNull(apkInfo.unknownFiles);
assertEquals(7, apkInfo.unknownFiles.size());
assertEquals("8", apkInfo.unknownFiles.get("AssetBundle/assets/a.txt"));
assertEquals("8", apkInfo.unknownFiles.get("AssetBundle/b.txt"));
assertEquals("8", apkInfo.unknownFiles.get("hidden.file"));
assertEquals("8", apkInfo.unknownFiles.get("non\u007Fprintable.file"));
assertEquals("0", apkInfo.unknownFiles.get("stored.file"));
assertEquals("8", apkInfo.unknownFiles.get("unk_folder/unknown_file"));
assertEquals("8", apkInfo.unknownFiles.get("lib_bug603/bug603"));
}
}

View File

@ -14,35 +14,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package brut.androlib.yaml;
package brut.androlib.apk;
import brut.androlib.BaseTest;
import brut.androlib.TestUtils;
import brut.androlib.apk.ApkInfo;
import brut.common.BrutException;
import brut.directory.ExtFile;
import brut.util.OS;
import org.junit.BeforeClass;
import brut.androlib.exceptions.AndrolibException;
import org.junit.Test;
import java.io.File;
import static org.junit.Assert.*;
public class ConsistentPropertyTest extends BaseTest {
@BeforeClass
public static void beforeClass() throws Exception {
TestUtils.cleanFrameworkFile();
sTmpDir = new ExtFile(OS.createTempDirectory());
sTestNewDir = new ExtFile(sTmpDir, "yaml");
LOGGER.info("Unpacking yaml files...");
TestUtils.copyResourceDir(ConsistentPropertyTest.class, "decode/yaml/", sTestNewDir);
}
public class ConsistentPropertyTest {
@Test
public void testAssertingAllKnownApkInfoProperties() throws BrutException {
ApkInfo apkInfo = ApkInfo.load(new File(sTestNewDir, "basic"));
public void testAssertingAllKnownApkInfoProperties() throws AndrolibException {
ApkInfo apkInfo = ApkInfo.load(
this.getClass().getResourceAsStream("/apk/basic.yml"));
assertEquals("2.8.0", apkInfo.version);
assertEquals("basic.apk", apkInfo.getApkFileName());

View File

@ -0,0 +1,20 @@
package brut.androlib.apk;
import brut.androlib.exceptions.AndrolibException;
import org.junit.Test;
import static org.junit.Assert.*;
public class DoNotCompressHieroglyphTest {
@Test
public void testHieroglyph() throws AndrolibException {
ApkInfo apkInfo = ApkInfo.load(
this.getClass().getResourceAsStream("/apk/donotcompress_with_hieroglyph.yml"));
assertEquals("2.0.0", apkInfo.version);
assertEquals("testapp.apk", apkInfo.getApkFileName());
assertEquals(2, apkInfo.doNotCompress.size());
assertEquals("assets/AllAssetBundles/Andriod/tx_1001_冰原1", apkInfo.doNotCompress.get(0));
assertEquals("assets/AllAssetBundles/Andriod/tx_1001_冰原1.manifest", apkInfo.doNotCompress.get(1));
}
}

View File

@ -14,17 +14,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package brut.androlib.androlib;
package brut.androlib.apk;
import brut.androlib.BaseTest;
import brut.androlib.apk.ApkInfo;
import org.junit.Test;
import java.util.LinkedHashMap;
import java.util.Map;
import static org.junit.Assert.assertEquals;
public class InvalidSdkBoundingTest extends BaseTest {
public class InvalidSdkBoundingTest {
@Test
public void checkIfInvalidValuesPass() {

View File

@ -0,0 +1,32 @@
/*
* Copyright (C) 2010 Ryszard Wiśniewski <brut.alll@gmail.com>
* Copyright (C) 2010 Connor Tumbleson <connor.tumbleson@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package brut.androlib.apk;
import brut.androlib.exceptions.AndrolibException;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class MaliciousYamlTest {
@Test
public void testMaliciousYaml() throws AndrolibException {
ApkInfo apkInfo = ApkInfo.load(
this.getClass().getResourceAsStream("/apk/cve20220476.yml"));
assertEquals("2.6.1-ddc4bb-SNAPSHOT", apkInfo.version);
}
}

View File

@ -0,0 +1,104 @@
package brut.androlib.apk;
import org.junit.Test;
import static org.junit.Assert.*;
public class YamlLineTest {
@Test
public void testEmptyLine() {
YamlLine line = new YamlLine("");
assertEquals(0, line.indent);
assertTrue(line.isEmpty);
line = new YamlLine(" ");
assertEquals(0, line.indent);
assertTrue(line.isEmpty);
}
@Test
public void testComment() {
YamlLine line = new YamlLine("!ApkInfo.class");
assertTrue(line.isComment);
line = new YamlLine("# This is comment");
assertEquals(0, line.indent);
assertTrue(line.isComment);
assertEquals("", line.getKey());
assertEquals("This is comment", line.getValue());
line = new YamlLine(" # This is comment");
assertEquals(2, line.indent);
assertTrue(line.isComment);
assertEquals("", line.getKey());
assertEquals("This is comment", line.getValue());
}
@Test
public void testKeyLine() {
YamlLine line = new YamlLine("name:");
assertFalse(line.isComment);
assertEquals(0, line.indent);
assertEquals("name", line.getKey());
assertEquals("", line.getValue());
line = new YamlLine(" name:");
assertFalse(line.isComment);
assertEquals(2, line.indent);
assertEquals("name", line.getKey());
assertEquals("", line.getValue());
line = new YamlLine(":value");
assertFalse(line.isComment);
assertEquals(0, line.indent);
assertEquals("", line.getKey());
assertEquals("value", line.getValue());
line = new YamlLine(" : value ");
assertFalse(line.isComment);
assertEquals(2, line.indent);
assertEquals("", line.getKey());
assertEquals("value", line.getValue());
line = new YamlLine("name : value ");
assertFalse(line.isComment);
assertEquals(0, line.indent);
assertEquals("name", line.getKey());
assertEquals("value", line.getValue());
line = new YamlLine(" name : value ");
assertFalse(line.isComment);
assertEquals(2, line.indent);
assertEquals("name", line.getKey());
assertEquals("value", line.getValue());
line = new YamlLine(" name : value ::");
assertFalse(line.isComment);
assertEquals(2, line.indent);
assertEquals("name", line.getKey());
assertEquals("value", line.getValue());
// split this gives parts.length = 0!!
line = new YamlLine(":::");
assertFalse(line.isComment);
assertEquals(0, line.indent);
assertEquals("", line.getKey());
assertEquals("", line.getValue());
}
@Test
public void testItemLine() {
YamlLine line = new YamlLine("- val1");
assertTrue(line.isItem);
assertEquals(0, line.indent);
assertEquals("", line.getKey());
assertEquals("val1", line.getValue());
line = new YamlLine(" - val1: ff");
assertTrue(line.isItem);
assertEquals(2, line.indent);
assertEquals("", line.getKey());
assertEquals("val1: ff", line.getValue());
}
}

View File

@ -1,50 +0,0 @@
/*
* Copyright (C) 2010 Ryszard Wiśniewski <brut.alll@gmail.com>
* Copyright (C) 2010 Connor Tumbleson <connor.tumbleson@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package brut.androlib.yaml;
import brut.androlib.ApkBuilder;
import brut.androlib.BaseTest;
import brut.androlib.TestUtils;
import brut.androlib.Config;
import brut.common.BrutException;
import brut.directory.ExtFile;
import brut.util.OS;
import org.junit.BeforeClass;
import org.junit.Test;
import org.yaml.snakeyaml.constructor.ConstructorException;
import java.io.File;
public class MaliciousYamlTest extends BaseTest {
@BeforeClass
public static void beforeClass() throws Exception {
TestUtils.cleanFrameworkFile();
sTmpDir = new ExtFile(OS.createTempDirectory());
sTestNewDir = new ExtFile(sTmpDir, "cve20220476");
LOGGER.info("Unpacking cve20220476...");
TestUtils.copyResourceDir(MaliciousYamlTest.class, "yaml/cve20220476/", sTestNewDir);
}
@Test(expected = ConstructorException.class)
public void testMaliciousYamlNotLoaded() throws BrutException {
Config config = Config.getDefaultConfig();
File testApk = new File(sTmpDir, "cve20220476.apk");
new ApkBuilder(config, sTestNewDir).build(testApk);
}
}

View File

@ -0,0 +1,6 @@
version: 2.0.0
apkFileName: testapp.apk
doNotCompress:
- assets/AllAssetBundles/Andriod/tx_1001_冰原1
- assets/AllAssetBundles/Andriod/tx_1001_冰原1.manifest

View File

@ -0,0 +1,22 @@
!!brut.androlib.meta.MetaInfo
version: 2.0.0
apkFileName: standard.apk
compressionType: false
doNotCompress:
- resources.arsc
isFrameworkApk: false
packageInfo:
forcedPackageId: '127'
renameManifestPackage: null
sdkInfo:
minSdkVersion: '25'
targetSdkVersion: '30'
sharedLibrary: false
sparseResources: false
usesFramework:
ids:
- 1
tag: null
versionInfo:
versionCode: null
versionName: null

View File

@ -0,0 +1,26 @@
!!brut.androlib.meta.MetaInfo
apkFileName: basic.apk
compressionType: false
doNotCompress:
- resources.arsc
- png
isFrameworkApk: false
packageInfo:
forcedPackageId: '127'
renameManifestPackage: 'com.test.basic'
sdkInfo:
minSdkVersion: '4'
maxSdkVersion: '30'
targetSdkVersion: '22'
sharedLibrary: false
sparseResources: true
unknownFiles:
hidden.file: 1
usesFramework:
ids:
- 1
tag: 'tag'
version: 2.8.0
versionInfo:
versionCode: '71'
versionName: 1.0.70

View File

@ -0,0 +1,22 @@
!!brut.androlib.meta.MetaInfo
apkFileName: standard.apk
version: 2.0.0
compressionType: false
doNotCompress:
- resources.arsc
isFrameworkApk: false
packageInfo:
forcedPackageId: '127'
renameManifestPackage: null
sdkInfo:
minSdkVersion: '25'
targetSdkVersion: '30'
sharedLibrary: false
sparseResources: false
usesFramework:
ids:
- 1
tag: null
versionInfo:
versionCode: null
versionName: null

View File

@ -0,0 +1,22 @@
!!brut.androlib.meta.MetaInfo
apkFileName: standard.apk
compressionType: false
doNotCompress:
- resources.arsc
isFrameworkApk: false
packageInfo:
forcedPackageId: '127'
renameManifestPackage: null
sdkInfo:
minSdkVersion: '25'
targetSdkVersion: '30'
sharedLibrary: false
sparseResources: false
usesFramework:
ids:
- 1
tag: null
version: 2.8.1
versionInfo:
versionCode: null
versionName: null

View File

@ -0,0 +1,25 @@
!!brut.androlib.meta.MetaInfo
apkFileName: standard.apk
compressionType: false
test: test
doNotCompress:
- resources.arsc
isFrameworkApk: false
packageInfo:
forcedPackageId: '127'
renameManifestPackage: null
test2: test2
sdkInfo:
minSdkVersion: '25'
targetSdkVersion: '30'
sharedLibrary: false
sparseResources: false
usesFramework:
ids:
- 1
tag: null
test3: test3
version: 2.8.1
versionInfo:
versionCode: null
versionName: null

View File

@ -0,0 +1,25 @@
version: 2.0.0
apkFileName: testapp.apk
isFrameworkApk: false
usesFramework:
ids:
- 1
packageInfo:
forcedPackageId: '127'
versionInfo:
versionCode: '1'
versionName: '1.0'
compressionType: false
doNotCompress:
- assets/0byte_file.jpg
- arsc
- png
- mp3
unknownFiles:
AssetBundle/assets/a.txt: '8'
AssetBundle/b.txt: '8'
hidden.file: '8'
non\u007Fprintable.file: '8'
stored.file: '0'
unk_folder/unknown_file: '8'
lib_bug603/bug603: '8'

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" android:compileSdkVersion="30" android:compileSdkVersionCodename="11" package="com.ibotpeaches.cve20220476" platformBuildVersionCode="30" platformBuildVersionName="11">
<application android:debuggable="true" android:forceQueryable="true">
</application>
</manifest>