Skip to content

Commit c9fac4b

Browse files
authored
fix: generate correct metadata when overflowing signed short values (#1821)
1 parent ba50f03 commit c9fac4b

File tree

3 files changed

+56
-6
lines changed

3 files changed

+56
-6
lines changed

test-app/build-tools/android-metadata-generator/src/src/com/telerik/metadata/Generator.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ public class Generator {
2727
private static final String MDG_BLACKLIST = "blacklist.mdg";
2828
private static final String METADATA_JAVA_OUT = "mdg-java-out.txt";
2929

30+
private static boolean verbose_mode = false;
31+
3032
/**
3133
* @param args arguments
3234
*/
@@ -69,7 +71,13 @@ public static void main(String[] args) {
6971
FileOutputStream oss = new FileOutputStream(new File(metadataOutputDir, "treeStringsStream.dat"));
7072
FileStreamWriter outStringsStream = new FileStreamWriter(oss);
7173

72-
new Writer(outNodeStream, outValueStream, outStringsStream).writeTree(root);
74+
if (verbose_mode) {
75+
FileOutputStream ods = new FileOutputStream(new File("metadata-debug.json"));
76+
FileStreamWriter outDebugStream = new FileStreamWriter(ods);
77+
new Writer(outNodeStream, outValueStream, outStringsStream, outDebugStream).writeTree(root);
78+
} else {
79+
new Writer(outNodeStream, outValueStream, outStringsStream).writeTree(root);
80+
}
7381
} catch (Throwable ex) {
7482
System.err.println(String.format("Error executing Metadata Generator: %s", ex.getMessage()));
7583
ex.printStackTrace(System.out);
@@ -83,6 +91,7 @@ private static void enableFlaggedFeatures(String[] args) {
8391
String filePath = arg.replace(ANALYTICS_ARGUMENT_BEGINNING, "");
8492
AnalyticsConfiguration.enableAnalytics(filePath);
8593
} else if (VERBOSE_FLAG_NAME.equals(arg)) {
94+
verbose_mode = true;
8695
MetadataFilterConsoleLogger.INSTANCE.setEnabled(true);
8796
} else if (SKIP_FLAG_NAME.equals(arg)) {
8897
System.out.println("Skipping metadata generation: skip flag used.");

test-app/build-tools/android-metadata-generator/src/src/com/telerik/metadata/Writer.java

+33-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.telerik.metadata;
22

3+
import com.google.gson.JsonArray;
4+
import com.google.gson.JsonObject;
35
import com.telerik.metadata.TreeNode.FieldInfo;
46
import com.telerik.metadata.TreeNode.MethodInfo;
57

@@ -10,6 +12,7 @@
1012
import java.nio.charset.StandardCharsets;
1113
import java.util.ArrayDeque;
1214
import java.util.HashMap;
15+
import java.util.HashSet;
1316
import java.util.List;
1417
import java.util.Optional;
1518

@@ -18,14 +21,20 @@ public class Writer {
1821
private final StreamWriter outNodeStream;
1922
private final StreamWriter outValueStream;
2023
private final StreamWriter outStringsStream;
24+
private final StreamWriter outDebugStream;
2125

2226
private int commonInterfacePrefixPosition;
2327

2428
public Writer(StreamWriter outNodeStream, StreamWriter outValueStream,
2529
StreamWriter outStringsStream) {
30+
this(outNodeStream, outValueStream, outStringsStream, null);
31+
}
32+
public Writer(StreamWriter outNodeStream, StreamWriter outValueStream,
33+
StreamWriter outStringsStream, StreamWriter outDebugStream) {
2634
this.outNodeStream = outNodeStream;
2735
this.outValueStream = outValueStream;
2836
this.outStringsStream = outStringsStream;
37+
this.outDebugStream = outDebugStream;
2938
}
3039

3140
private final static byte[] writeUniqueName_lenBuff = new byte[2];
@@ -214,6 +223,10 @@ public void writeTree(TreeNode root) throws Exception {
214223
d.push(root);
215224
while (!d.isEmpty()) {
216225
TreeNode n = d.pollFirst();
226+
if (Short.toUnsignedInt((short)(curId + 1)) < Short.toUnsignedInt(curId)) {
227+
// we have overflowed our maximum (16 bit) metadata size
228+
throw new Exception("Metadata is too big and has overflown our current limit, please report this issue");
229+
}
217230
n.id = n.firstChildId = n.nextSiblingId = curId++;
218231

219232
String name = n.getName();
@@ -351,7 +364,7 @@ public void writeTree(TreeNode root) throws Exception {
351364
while (!d.isEmpty()) {
352365
TreeNode n = d.pollFirst();
353366

354-
nodeData[0] = n.firstChildId + (n.nextSiblingId << 16);
367+
nodeData[0] = (n.firstChildId & 0xFFFF) | (n.nextSiblingId << 16);
355368
nodeData[1] = n.offsetName;
356369
nodeData[2] = n.offsetValue;
357370

@@ -364,5 +377,24 @@ public void writeTree(TreeNode root) throws Exception {
364377

365378
outNodeStream.flush();
366379
outNodeStream.close();
380+
381+
if (outDebugStream != null) {
382+
d.push(root);
383+
JsonArray rootArray = new JsonArray();
384+
while (!d.isEmpty()) {
385+
TreeNode n = d.pollFirst();
386+
JsonObject obj = new JsonObject();
387+
obj.addProperty("id", Short.toUnsignedInt(n.id));
388+
obj.addProperty("nextSiblingId", Short.toUnsignedInt(n.nextSiblingId));
389+
obj.addProperty("firstChildId", Short.toUnsignedInt(n.firstChildId));
390+
obj.addProperty("name", n.getName());
391+
obj.addProperty("nodeType", n.nodeType);
392+
rootArray.add(obj);
393+
d.addAll(n.children);
394+
}
395+
outDebugStream.write(rootArray.toString().getBytes());
396+
outDebugStream.flush();
397+
outDebugStream.close();
398+
}
367399
}
368400
}

test-app/runtime/src/main/cpp/MetadataReader.cpp

+13-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "MetadataMethodInfo.h"
33
#include "Util.h"
44
#include <sstream>
5+
#include <android/log.h>
56

67
using namespace std;
78
using namespace tns;
@@ -54,20 +55,28 @@ MetadataTreeNode* MetadataReader::BuildTree() {
5455
while (true) {
5556

5657
uint16_t childNodeDataId = childNodeData - rootNodeData;
58+
59+
MetadataTreeNode* childNode;
5760
// node (and its next siblings) already visited, so we don't need to visit it again
5861
if (m_v[childNodeDataId] != emptyNode) {
62+
childNode = m_v[childNodeDataId];
63+
__android_log_print(ANDROID_LOG_ERROR, "TNS.error", "Consistency error in metadata. A child should never have been visited before its parent. Parent: %s Child: %s. Child metadata id: %u", node->name.c_str(), childNode->name.c_str(), childNodeDataId);
5964
break;
65+
} else {
66+
childNode = new MetadataTreeNode;
67+
childNode->name = ReadName(childNodeData->offsetName);
68+
childNode->offsetValue = childNodeData->offsetValue;
6069
}
61-
62-
MetadataTreeNode* childNode = new MetadataTreeNode;
6370
childNode->parent = node;
64-
childNode->name = ReadName(childNodeData->offsetName);
65-
childNode->offsetValue = childNodeData->offsetValue;
6671

6772
node->children->push_back(childNode);
6873

6974
m_v[childNodeDataId] = childNode;
7075

76+
if (childNodeDataId == childNodeData->nextSiblingId) {
77+
break;
78+
}
79+
7180
childNodeData = rootNodeData + childNodeData->nextSiblingId;
7281
}
7382
}

0 commit comments

Comments
 (0)