OSDN Git Service

[DO NOT MERGE] Check bounds in offsetToPtr
[android-x86/frameworks-base.git] / tools / aapt / AaptXml.cpp
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <androidfw/ResourceTypes.h>
18 #include <utils/String8.h>
19
20 #include "AaptXml.h"
21
22 using namespace android;
23
24 namespace AaptXml {
25
26 static String8 getStringAttributeAtIndex(const ResXMLTree& tree, ssize_t attrIndex,
27         String8* outError) {
28     Res_value value;
29     if (tree.getAttributeValue(attrIndex, &value) < 0) {
30         if (outError != NULL) {
31             *outError = "could not find attribute at index";
32         }
33         return String8();
34     }
35
36     if (value.dataType != Res_value::TYPE_STRING) {
37         if (outError != NULL) {
38             *outError = "attribute is not a string value";
39         }
40         return String8();
41     }
42
43     size_t len;
44     const char16_t* str = tree.getAttributeStringValue(attrIndex, &len);
45     return str ? String8(str, len) : String8();
46 }
47
48 static int32_t getIntegerAttributeAtIndex(const ResXMLTree& tree, ssize_t attrIndex,
49     int32_t defValue, String8* outError) {
50     Res_value value;
51     if (tree.getAttributeValue(attrIndex, &value) < 0) {
52         if (outError != NULL) {
53             *outError = "could not find attribute at index";
54         }
55         return defValue;
56     }
57
58     if (value.dataType < Res_value::TYPE_FIRST_INT
59             || value.dataType > Res_value::TYPE_LAST_INT) {
60         if (outError != NULL) {
61             *outError = "attribute is not an integer value";
62         }
63         return defValue;
64     }
65     return value.data;
66 }
67
68
69 ssize_t indexOfAttribute(const ResXMLTree& tree, uint32_t attrRes) {
70     size_t attrCount = tree.getAttributeCount();
71     for (size_t i = 0; i < attrCount; i++) {
72         if (tree.getAttributeNameResID(i) == attrRes) {
73             return (ssize_t)i;
74         }
75     }
76     return -1;
77 }
78
79 String8 getAttribute(const ResXMLTree& tree, const char* ns,
80         const char* attr, String8* outError) {
81     ssize_t idx = tree.indexOfAttribute(ns, attr);
82     if (idx < 0) {
83         return String8();
84     }
85     return getStringAttributeAtIndex(tree, idx, outError);
86 }
87
88 String8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError) {
89     ssize_t idx = indexOfAttribute(tree, attrRes);
90     if (idx < 0) {
91         return String8();
92     }
93     return getStringAttributeAtIndex(tree, idx, outError);
94 }
95
96 String8 getResolvedAttribute(const ResTable& resTable, const ResXMLTree& tree,
97         uint32_t attrRes, String8* outError) {
98     ssize_t idx = indexOfAttribute(tree, attrRes);
99     if (idx < 0) {
100         return String8();
101     }
102     Res_value value;
103     if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
104         if (value.dataType == Res_value::TYPE_STRING) {
105             size_t len;
106             const char16_t* str = tree.getAttributeStringValue(idx, &len);
107             return str ? String8(str, len) : String8();
108         }
109         resTable.resolveReference(&value, 0);
110         if (value.dataType != Res_value::TYPE_STRING) {
111             if (outError != NULL) {
112                 *outError = "attribute is not a string value";
113             }
114             return String8();
115         }
116     }
117     size_t len;
118     const Res_value* value2 = &value;
119     const char16_t* str = resTable.valueToString(value2, 0, NULL, &len);
120     return str ? String8(str, len) : String8();
121 }
122
123 int32_t getIntegerAttribute(const ResXMLTree& tree, const char* ns,
124         const char* attr, int32_t defValue, String8* outError) {
125     ssize_t idx = tree.indexOfAttribute(ns, attr);
126     if (idx < 0) {
127         return defValue;
128     }
129     return getIntegerAttributeAtIndex(tree, idx, defValue, outError);
130 }
131
132 int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes, int32_t defValue,
133         String8* outError) {
134     ssize_t idx = indexOfAttribute(tree, attrRes);
135     if (idx < 0) {
136         return defValue;
137     }
138     return getIntegerAttributeAtIndex(tree, idx, defValue, outError);
139 }
140
141 int32_t getResolvedIntegerAttribute(const ResTable& resTable, const ResXMLTree& tree,
142         uint32_t attrRes, int32_t defValue, String8* outError) {
143     ssize_t idx = indexOfAttribute(tree, attrRes);
144     if (idx < 0) {
145         return defValue;
146     }
147     Res_value value;
148     if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
149         if (value.dataType == Res_value::TYPE_REFERENCE) {
150             resTable.resolveReference(&value, 0);
151         }
152         if (value.dataType < Res_value::TYPE_FIRST_INT
153                 || value.dataType > Res_value::TYPE_LAST_INT) {
154             if (outError != NULL) {
155                 *outError = "attribute is not an integer value";
156             }
157             return defValue;
158         }
159     }
160     return value.data;
161 }
162
163 void getResolvedResourceAttribute(const ResTable& resTable, const ResXMLTree& tree,
164         uint32_t attrRes, Res_value* outValue, String8* outError) {
165     ssize_t idx = indexOfAttribute(tree, attrRes);
166     if (idx < 0) {
167         if (outError != NULL) {
168             *outError = "attribute could not be found";
169         }
170         return;
171     }
172     if (tree.getAttributeValue(idx, outValue) != NO_ERROR) {
173         if (outValue->dataType == Res_value::TYPE_REFERENCE) {
174             resTable.resolveReference(outValue, 0);
175         }
176         // The attribute was found and was resolved if need be.
177         return;
178     }
179     if (outError != NULL) {
180         *outError = "error getting resolved resource attribute";
181     }
182 }
183
184 } // namespace AaptXml