mirror of https://github.com/status-im/NimYAML.git
made anchor resolution during deserialization safer
This commit is contained in:
parent
aa65c066d5
commit
4305bccbf0
|
@ -211,7 +211,7 @@ suite "Lexer":
|
||||||
pl("bar baz"), dirE(), i(0), pl("derp"), e())
|
pl("bar baz"), dirE(), i(0), pl("derp"), e())
|
||||||
|
|
||||||
test "Sequence with compact maps":
|
test "Sequence with compact maps":
|
||||||
assertEquals("""- a: drzw\n- b""", i(0), ss(), pl("a"), mv(), pl("drzw"), i(0), ss(), pl("b"), e())
|
assertEquals("- a: drzw\n- b", i(0), si(), pl("a"), mv(), pl("drzw"), i(0), si(), pl("b"), e())
|
||||||
|
|
||||||
test "Empty lines":
|
test "Empty lines":
|
||||||
assertEquals("""block: foo
|
assertEquals("""block: foo
|
||||||
|
|
|
@ -272,14 +272,3 @@ proc `$`*(event: Event): string {.raises: [].} =
|
||||||
of ssFolded: result &= " >"
|
of ssFolded: result &= " >"
|
||||||
result &= yamlTestSuiteEscape(event.scalarContent)
|
result &= yamlTestSuiteEscape(event.scalarContent)
|
||||||
of yamlAlias: result = "=ALI *" & $event.aliasTarget
|
of yamlAlias: result = "=ALI *" & $event.aliasTarget
|
||||||
|
|
||||||
type
|
|
||||||
TypeID* = int ## unique ID of a type
|
|
||||||
|
|
||||||
var nextTypeID {.compileTime.}: TypeID
|
|
||||||
|
|
||||||
proc typeID*(T:typedesc): TypeID =
|
|
||||||
const id = nextTypeID
|
|
||||||
static:
|
|
||||||
inc nextTypeID
|
|
||||||
return id
|
|
|
@ -138,7 +138,7 @@ proc composeNode(s: var YamlStream, tagLib: TagLibrary,
|
||||||
template addAnchor(c: ConstructionContext, target: Anchor) =
|
template addAnchor(c: ConstructionContext, target: Anchor) =
|
||||||
if target != yAnchorNone:
|
if target != yAnchorNone:
|
||||||
yAssert(not c.refs.hasKey(target))
|
yAssert(not c.refs.hasKey(target))
|
||||||
c.refs[target] = (id: typeID(YamlNode), p: cast[pointer](result))
|
c.refs[target] = (tag: yamlTag(YamlNode), p: cast[pointer](result))
|
||||||
|
|
||||||
var start: Event
|
var start: Event
|
||||||
shallowCopy(start, s.next())
|
shallowCopy(start, s.next())
|
||||||
|
|
|
@ -32,7 +32,7 @@ type
|
||||||
|
|
||||||
ConstructionContext* = ref object
|
ConstructionContext* = ref object
|
||||||
## Context information for the process of constructing Nim values from YAML.
|
## Context information for the process of constructing Nim values from YAML.
|
||||||
refs*: Table[Anchor, tuple[id: TypeID, p: pointer]]
|
refs*: Table[Anchor, tuple[tag: Tag, p: pointer]]
|
||||||
|
|
||||||
YamlConstructionError* = object of YamlLoadingError
|
YamlConstructionError* = object of YamlLoadingError
|
||||||
## Exception that may be raised when constructing data objects from a
|
## Exception that may be raised when constructing data objects from a
|
||||||
|
@ -86,7 +86,7 @@ proc representChild*[O](value: O, ts: TagStyle, c: SerializationContext)
|
||||||
|
|
||||||
proc newConstructionContext*(): ConstructionContext =
|
proc newConstructionContext*(): ConstructionContext =
|
||||||
new(result)
|
new(result)
|
||||||
result.refs = initTable[Anchor, tuple[id: TypeID, p: pointer]]()
|
result.refs = initTable[Anchor, tuple[tag: Tag, p: pointer]]()
|
||||||
|
|
||||||
proc newSerializationContext*(s: AnchorStyle,
|
proc newSerializationContext*(s: AnchorStyle,
|
||||||
putImpl: proc(e: Event) {.raises: [], closure.}):
|
putImpl: proc(e: Event) {.raises: [], closure.}):
|
||||||
|
@ -1223,14 +1223,18 @@ proc constructChild*[O](s: var YamlStream, c: ConstructionContext,
|
||||||
discard s.next()
|
discard s.next()
|
||||||
return
|
return
|
||||||
elif e.kind == yamlAlias:
|
elif e.kind == yamlAlias:
|
||||||
result = cast[ref O](c.refs.getOrDefault(e.aliasTarget).p)
|
let val = c.refs.getOrDefault(e.aliasTarget)
|
||||||
|
if val.tag != yamlTag(O):
|
||||||
|
raise constructionError(s, e.startPos,
|
||||||
|
"alias node refers to object of incompatible type")
|
||||||
|
result = cast[ref O](val.p)
|
||||||
discard s.next()
|
discard s.next()
|
||||||
return
|
return
|
||||||
new(result)
|
new(result)
|
||||||
template removeAnchor(anchor: var Anchor) {.dirty.} =
|
template removeAnchor(anchor: var Anchor) {.dirty.} =
|
||||||
if anchor != yAnchorNone:
|
if anchor != yAnchorNone:
|
||||||
yAssert(not c.refs.hasKey(anchor))
|
yAssert(not c.refs.hasKey(anchor))
|
||||||
c.refs[anchor] = (0, cast[pointer](result))
|
c.refs[anchor] = (yamlTag(O), cast[pointer](result))
|
||||||
anchor = yAnchorNone
|
anchor = yAnchorNone
|
||||||
|
|
||||||
case e.kind
|
case e.kind
|
||||||
|
|
Loading…
Reference in New Issue