Skip to content

Commit 80a1605

Browse files
authored
Merge pull request #74 from shogo82148/fix-isseu73
fix panics in XMLFile.readElement
2 parents 448b8b3 + a2da393 commit 80a1605

File tree

3 files changed

+63
-14
lines changed

3 files changed

+63
-14
lines changed

common.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,16 @@ type ResValue struct {
115115
}
116116

117117
// GetString returns a string referenced by ref.
118+
// It panics if the pool doesn't contain ref.
118119
func (pool *ResStringPool) GetString(ref ResStringPoolRef) string {
119120
return pool.Strings[int(ref)]
120121
}
121122

123+
// HasString returns whether the pool contains ref.
124+
func (pool *ResStringPool) HasString(ref ResStringPoolRef) bool {
125+
return int(ref) >= 0 && int(ref) < len(pool.Strings)
126+
}
127+
122128
func readStringPool(sr *io.SectionReader) (*ResStringPool, error) {
123129
sp := new(ResStringPool)
124130
if err := binary.Read(sr, binary.LittleEndian, &sp.Header); err != nil {

xml.go

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,19 @@ import (
1212
// XMLFile is an XML file expressed in binary format.
1313
type XMLFile struct {
1414
stringPool *ResStringPool
15-
resourceMap []uint32
1615
notPrecessedNS map[ResStringPoolRef]ResStringPoolRef
1716
namespaces xmlNamespaces
1817
xmlBuffer bytes.Buffer
1918
}
2019

20+
type InvalidReferenceError struct {
21+
Ref ResStringPoolRef
22+
}
23+
24+
func (e *InvalidReferenceError) Error() string {
25+
return fmt.Sprintf("androidbinary: invalid reference: 0x%08X", e.Ref)
26+
}
27+
2128
type (
2229
xmlNamespaces struct {
2330
l []namespaceVal
@@ -30,7 +37,6 @@ type (
3037

3138
func (x *xmlNamespaces) add(key ResStringPoolRef, value ResStringPoolRef) {
3239
x.l = append(x.l, namespaceVal{key: key, value: value})
33-
return
3440
}
3541

3642
func (x *xmlNamespaces) remove(key ResStringPoolRef) {
@@ -41,7 +47,6 @@ func (x *xmlNamespaces) remove(key ResStringPoolRef) {
4147
return
4248
}
4349
}
44-
return
4550
}
4651

4752
func (x *xmlNamespaces) get(key ResStringPoolRef) ResStringPoolRef {
@@ -164,10 +169,15 @@ func (f *XMLFile) readChunk(r io.ReaderAt, offset int64) (*ResChunkHeader, error
164169
}
165170

166171
// GetString returns a string referenced by ref.
172+
// It panics if the pool doesn't contain ref.
167173
func (f *XMLFile) GetString(ref ResStringPoolRef) string {
168174
return f.stringPool.GetString(ref)
169175
}
170176

177+
func (f *XMLFile) HasString(ref ResStringPoolRef) bool {
178+
return f.stringPool.HasString(ref)
179+
}
180+
171181
func (f *XMLFile) readStartNamespace(sr *io.SectionReader) error {
172182
header := new(ResXMLTreeNode)
173183
if err := binary.Read(sr, binary.LittleEndian, header); err != nil {
@@ -207,12 +217,24 @@ func (f *XMLFile) readEndNamespace(sr *io.SectionReader) error {
207217
return nil
208218
}
209219

210-
func (f *XMLFile) addNamespacePrefix(ns, name ResStringPoolRef) string {
220+
func (f *XMLFile) addNamespacePrefix(ns, name ResStringPoolRef) (string, error) {
221+
if !f.HasString(name) {
222+
return "", &InvalidReferenceError{Ref: name}
223+
}
224+
211225
if ns != NilResStringPoolRef {
212-
prefix := f.GetString(f.namespaces.get(ns))
213-
return fmt.Sprintf("%s:%s", prefix, f.GetString(name))
226+
ref := f.namespaces.get(ns)
227+
if ref == 0 {
228+
return "", &InvalidReferenceError{Ref: ns}
229+
}
230+
if !f.HasString(ref) {
231+
return "", &InvalidReferenceError{Ref: ref}
232+
}
233+
prefix := f.GetString(ref)
234+
235+
return fmt.Sprintf("%s:%s", prefix, f.GetString(name)), nil
214236
}
215-
return f.GetString(name)
237+
return f.GetString(name), nil
216238
}
217239

218240
func (f *XMLFile) readStartElement(sr *io.SectionReader) error {
@@ -229,7 +251,12 @@ func (f *XMLFile) readStartElement(sr *io.SectionReader) error {
229251
return nil
230252
}
231253

232-
fmt.Fprintf(&f.xmlBuffer, "<%s", f.addNamespacePrefix(ext.NS, ext.Name))
254+
tag, err := f.addNamespacePrefix(ext.NS, ext.Name)
255+
if err != nil {
256+
return err
257+
}
258+
f.xmlBuffer.WriteString("<")
259+
f.xmlBuffer.WriteString(tag)
233260

234261
// output XML namespaces
235262
if f.notPrecessedNS != nil {
@@ -275,7 +302,11 @@ func (f *XMLFile) readStartElement(sr *io.SectionReader) error {
275302
}
276303
}
277304

278-
fmt.Fprintf(&f.xmlBuffer, " %s=\"", f.addNamespacePrefix(attr.NS, attr.Name))
305+
name, err := f.addNamespacePrefix(attr.NS, attr.Name)
306+
if err != nil {
307+
return err
308+
}
309+
fmt.Fprintf(&f.xmlBuffer, " %s=\"", name)
279310
xml.Escape(&f.xmlBuffer, []byte(value))
280311
fmt.Fprint(&f.xmlBuffer, "\"")
281312
offset += int64(ext.AttributeSize)
@@ -296,6 +327,10 @@ func (f *XMLFile) readEndElement(sr *io.SectionReader) error {
296327
if err := binary.Read(sr, binary.LittleEndian, ext); err != nil {
297328
return err
298329
}
299-
fmt.Fprintf(&f.xmlBuffer, "</%s>", f.addNamespacePrefix(ext.NS, ext.Name))
330+
tag, err := f.addNamespacePrefix(ext.NS, ext.Name)
331+
if err != nil {
332+
return err
333+
}
334+
fmt.Fprintf(&f.xmlBuffer, "</%s>", tag)
300335
return nil
301336
}

xml_test.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,20 @@ func TestAddNamespacePrefix(t *testing.T) {
162162
f.stringPool = new(ResStringPool)
163163
f.stringPool.Strings = []string{"", "name", "prefix", "http://example.com"}
164164

165-
if actual := f.addNamespacePrefix(NilResStringPoolRef, nameRef); actual != "name" {
166-
t.Errorf("got %v want name", actual)
165+
got, err := f.addNamespacePrefix(NilResStringPoolRef, nameRef)
166+
if err != nil {
167+
t.Errorf("got %v want no error", err)
168+
}
169+
if got != "name" {
170+
t.Errorf("got %v want name", got)
167171
}
168172

169-
if actual := f.addNamespacePrefix(uriRef, nameRef); actual != "prefix:name" {
170-
t.Errorf("got %v want prefix:name", actual)
173+
got, err = f.addNamespacePrefix(uriRef, nameRef)
174+
if err != nil {
175+
t.Errorf("got %v want no error", err)
176+
}
177+
if got != "prefix:name" {
178+
t.Errorf("got %v want prefix:name", got)
171179
}
172180
}
173181

0 commit comments

Comments
 (0)