stencilproject / Stencil

Stencil is a simple and powerful template language for Swift.
https://stencil.fuller.li
BSD 2-Clause "Simplified" License
2.34k stars 224 forks source link

SIGABRT crash with key value coding #231

Closed mbrandonw closed 6 years ago

mbrandonw commented 6 years ago

Hi! I noticed that if you reference a field for a variable that doesn't exist, you get a crash with SIGABRT. For example this template render:

try Template(templateString: "{{ user.name }}").render(["user": "Blob"])

will crash.

To fix I believe all you have to do is guard this value(forKey:) call:

https://github.com/stencilproject/Stencil/blob/00e71c1b4dc2ec6c0f87841a10e34299e6059fcc/Sources/Variable.swift#L107

with this:

        if object.responds(to: Selector(bit)) {
          current = object.value(forKey: bit)
        }

Does the current code work as expected, or is it worth fixing?

Thanks!

ilyapuchka commented 6 years ago

@mbrandonw I was looking for that the whole day since read your article, but didn't realise that one could use selector for that. I'm not sure it would work though with custom property accessors and instance variables, didn't do ObjC for a while, but that should be rare anyway. Thanks for the tip, I'll make a PR. I suppose we will just return nil for now, but can consider better options later in general.

mbrandonw commented 6 years ago

Cool, thanks for looking into it! FWIW I did that because I found it in the docs:

https://stencil.fuller.li/en/latest/templates.html#variables

[
  "item": [
    "name": "John"
  ],
  "key": "name"
]

"The result of {{ item[key] }} will be the same as {{ item.name }}. It will first evaluate the result of {{ key }}, and only then evaluate the lookup expression."