@@ -908,68 +908,80 @@ internal struct XMLPlistScanner {
908
908
}
909
909
}
910
910
911
- func determineTag ( ) throws -> XMLPlistTag ? {
911
+ mutating func readTag ( ) throws -> XMLPlistTag ? {
912
912
let marker = reader. readIndex
913
- switch reader. char ( at: marker) {
913
+ var tag : XMLPlistTag ?
914
+ switch reader. peek ( ) {
914
915
case UInt8 ( ascii: " a " ) : // Array
915
916
if matches ( tag: . array, at: marker, until: reader. endIndex) {
916
- return . array
917
+ tag = . array
917
918
}
918
919
case UInt8 ( ascii: " d " ) : // Dictionary, data, or date
919
920
if matches ( tag: . dict, at: marker, until: reader. endIndex) {
920
- return . dict
921
+ tag = . dict
921
922
} else if matches ( tag: . data, at: marker, until: reader. endIndex) {
922
- return . data
923
+ tag = . data
923
924
} else if matches ( tag: . date, at: marker, until: reader. endIndex) {
924
- return . date
925
+ tag = . date
925
926
}
926
927
case UInt8 ( ascii: " f " ) : // false (boolean)
927
928
if matches ( tag: . false , at: marker, until: reader. endIndex) {
928
- return . false
929
+ tag = . false
929
930
}
930
931
case UInt8 ( ascii: " i " ) : // integer
931
932
if matches ( tag: . integer, at: marker, until: reader. endIndex) {
932
- return . integer
933
+ tag = . integer
933
934
}
934
935
case UInt8 ( ascii: " k " ) : // Key of a dictionary
935
936
if matches ( tag: . key, at: marker, until: reader. endIndex) {
936
- return . key
937
+ tag = . key
937
938
}
938
939
case UInt8 ( ascii: " p " ) : // Plist
939
940
if matches ( tag: . plist, at: marker, until: reader. endIndex) {
940
- return . plist
941
+ tag = . plist
941
942
}
942
943
case UInt8 ( ascii: " r " ) : // real
943
944
if matches ( tag: . real, at: marker, until: reader. endIndex) {
944
- return . real
945
+ tag = . real
945
946
}
946
947
case UInt8 ( ascii: " s " ) : // String
947
948
if matches ( tag: . string, at: marker, until: reader. endIndex) {
948
- return . string
949
+ tag = . string
949
950
}
950
951
case UInt8 ( ascii: " t " ) : // true (boolean)
951
952
if matches ( tag: . true , at: marker, until: reader. endIndex) {
952
- return . true
953
+ tag = . true
953
954
}
954
- case . _space, . _tab, . _newline, . _return, . _closeangle:
955
- throw XMLPlistError . malformedTag ( line: reader. lineNumber)
956
955
default :
957
956
break
958
957
}
959
- return nil
958
+
959
+ guard let tag else {
960
+ return nil
961
+ }
962
+
963
+ // Tag names must be delimited either by whitespace or a '>' or `/` character to be valid.
964
+ reader. advance ( tag. tagLength)
965
+ switch reader. peek ( ) {
966
+ case . _closeangle, . _forwardslash, . _space, . _tab, . _newline, . _return:
967
+ return tag
968
+ default :
969
+ return nil
970
+ }
960
971
}
961
972
962
973
mutating func peekXMLElement( ) throws -> ( XMLPlistTag , isEmpty: Bool ) {
963
- guard let tag = try determineTag ( ) else {
964
- let badTagStart = reader. readIndex
965
- while let ch = reader. read ( ) , ch != . _closeangle { }
966
- let badTagEnd = reader. readIndex
967
- let markerStr = String . _tryFromUTF8 ( reader. fullBuffer [ badTagStart..< badTagEnd] ) ?? " <unparseable> "
974
+ let tagStart = reader. readIndex
975
+ guard let tag = try readTag ( ) else {
976
+ var idx = reader. readIndex
977
+ while idx < reader. endIndex, reader. char ( at: idx) != . _closeangle {
978
+ reader. advance ( & idx)
979
+ }
980
+ let markerStr = String . _tryFromUTF8 ( reader. fullBuffer [ tagStart..< idx] ) ?? " <unparseable> "
968
981
throw XMLPlistError . other ( " Encountered unknown tag \( markerStr) on line \( reader. lineNumber) " )
969
982
}
970
983
971
- reader. advance ( tag. tagLength)
972
-
984
+ // Skip past any characters (whitespace or attributes) that may follow a valid tag name.
973
985
while let ch = reader. read ( ) , ch != . _closeangle { }
974
986
if reader. isAtEnd {
975
987
throw XMLPlistError . malformedTag ( line: reader. lineNumber)
0 commit comments