Discussion:
[Ur] No sql_injectable(_prim) xbody (or xml in general).
Peter Brottveit Bock
2017-11-02 19:59:19 UTC
Permalink
Hi,

It seems to me that it's not possible to store xml in a database. Is there any reason for this?

My understanding of ur/web is that the xml data type is—under the hood—simply a string. I therefore would have thought it would be trivial to store it in a database.

As a minimal example:

------------------
table db : { Elem : xbody }

fun display_db () =
queryX (SELECT * FROM db)
(fn row => row.Db.Elem)

fun add_to_db (x : xbody) : transaction unit =
dml (INSERT INTO db(Elem) VALUES ({[x]}))

fun main () =
add_to_db <xml> Hello </xml>;
display_db ()
------------------

fails with
------------------
example.ur:5:38: (to 5:43) Can't resolve type class instance
Class constraint:
sql_injectable (xml ([Dyn = (), MakeForm = (), Body = ()]) ([]) ([]))
Reduced to unresolvable:
sql_injectable_prim
(xml ([Dyn = (), MakeForm = (), Body = ()]) ([]) ([]))
------------------

— Peter
Adam Chlipala
2017-11-02 20:08:24 UTC
Permalink
You're right that there are currently no type-class instances for
storing XML in the SQL database.  At the moment, I can't remember any
good reasons for not adding an instance for all [xml] types. I'll plan
to do it, if no one adds a counterargument here in the next few days!
Post by Peter Brottveit Bock
Hi,
It seems to me that it's not possible to store xml in a database. Is there any reason for this?
My understanding of ur/web is that the xml data type is—under the hood—simply a string. I therefore would have thought it would be trivial to store it in a database.
------------------
table db : { Elem : xbody }
fun display_db () =
queryX (SELECT * FROM db)
(fn row => row.Db.Elem)
fun add_to_db (x : xbody) : transaction unit =
dml (INSERT INTO db(Elem) VALUES ({[x]}))
fun main () =
add_to_db <xml> Hello </xml>;
display_db ()
------------------
fails with
------------------
example.ur:5:38: (to 5:43) Can't resolve type class instance
sql_injectable (xml ([Dyn = (), MakeForm = (), Body = ()]) ([]) ([]))
sql_injectable_prim
(xml ([Dyn = (), MakeForm = (), Body = ()]) ([]) ([]))
------------------
— Peter
Artyom Shalkhakov
2017-11-03 03:19:40 UTC
Permalink
Hello Peter,
Post by Peter Brottveit Bock
Hi,
It seems to me that it's not possible to store xml in a database. Is there
any reason for this?
My understanding of ur/web is that the xml data type is—under the
hood—simply a string. I therefore would have thought it would be trivial to
store it in a database.
Storing it in a database is prone to XML/HTML injection (therefore the
general case is disallowed).

If you want to store in database, then you will have to print it to a
string and then parse it back into XML/HTML (for a strictly controlled
subset of XML/HTML).

There is a library for this use-case in UPO:

https://github.com/achlipala/upo/blob/master/html.urs
Post by Peter Brottveit Bock
------------------
table db : { Elem : xbody }
fun display_db () =
queryX (SELECT * FROM db)
(fn row => row.Db.Elem)
fun add_to_db (x : xbody) : transaction unit =
dml (INSERT INTO db(Elem) VALUES ({[x]}))
fun main () =
add_to_db <xml> Hello </xml>;
display_db ()
------------------
fails with
------------------
example.ur:5:38: (to 5:43) Can't resolve type class instance
sql_injectable (xml ([Dyn = (), MakeForm = (), Body = ()]) ([]) ([]))
sql_injectable_prim
(xml ([Dyn = (), MakeForm = (), Body = ()]) ([]) ([]))
------------------
— Peter
_______________________________________________
Ur mailing list
http://www.impredicative.com/cgi-bin/mailman/listinfo/ur
--
Cheers,
Artyom Shalkhakov
Adam Chlipala
2017-11-03 12:00:03 UTC
Permalink
Post by Peter Brottveit Bock
It seems to me that it's not possible to store xml in a database.
Is there any reason for this?
Storing it in a database is prone to XML/HTML injection (therefore the
general case is disallowed).
Right, that's true.  However, it shouldn't be a concern when only your
Ur/Web app accesses that database.

Still, overnight I thought of another issue: legitimate JavaScript code
within HTML fragments can become illegitimate across versions of your
Ur/Web app!  A global identifier may no longer exist, causing an
unbound-identifier exception when using HTML retrieved from the
database.  To me, this is the kiss of death, reminding me why this
feature deserves to be left out.
Peter Brottveit Bock
2017-11-03 12:58:17 UTC
Permalink
I don't really see the injection problem in the case of ur/web, since there is a strict separation between strings and xml. (I also just checked: it seems one can't send xml from the client to the server—which is good in case of malicious clients.)

I do see the problem with the javascript, though. Related to this, I was surprised to learn yesterday that all types are serializeable. Given the problem you just highlighted, this seems problematic!

Example code:
----------------------------
fun get_text () : transaction string =
return "hello world"

fun generate_page () : transaction xbody =
text <- source "";
return
<xml>
<hr/>
<dyn signal={
x <- signal text;
return <xml> {[x]} </xml>
}/>
<button value="click me"
onclick={fn _ => s <- rpc (get_text ()); set text s }
/>
</xml>

table t : { Elem : serialized xbody }

fun add_page () : transaction unit =
page <- generate_page ();
dml(INSERT INTO t(Elem) VALUES ({[serialize page]}))

fun main () : transaction page =
current_pages <-
queryX (SELECT * FROM t) (fn row => deserialize row.T.Elem);
return <xml>
<body>
<button value="add page"
onclick={fn _ => rpc (add_page ())}/>
<hr/>
{current_pages}
</body>
</xml>
----------------------------

Running this page, clicking on "add page", and then refreshing gives an error in Firefox's developer console.

— Peter
Post by Peter Brottveit Bock
It seems to me that it's not possible to store xml in a database.
Is there any reason for this?
Storing it in a database is prone to XML/HTML injection (therefore the
general case is disallowed).
Right, that's true.  However, it shouldn't be a concern when only your
Ur/Web app accesses that database.
Still, overnight I thought of another issue: legitimate JavaScript code
within HTML fragments can become illegitimate across versions of your
Ur/Web app!  A global identifier may no longer exist, causing an
unbound-identifier exception when using HTML retrieved from the
database.  To me, this is the kiss of death, reminding me why this
feature deserves to be left out.
_______________________________________________
Ur mailing list
http://www.impredicative.com/cgi-bin/mailman/listinfo/ur
Adam Chlipala
2017-11-03 14:08:07 UTC
Permalink
Actually, not all types are serializable, but you're right that XML
currently is!  This might call for more checking in the compiler for bad
type parameters of [serialize]/[deserialize]. Thanks for pointing it out.
Post by Peter Brottveit Bock
I don't really see the injection problem in the case of ur/web, since there is a strict separation between strings and xml. (I also just checked: it seems one can't send xml from the client to the server—which is good in case of malicious clients.)
I do see the problem with the javascript, though. Related to this, I was surprised to learn yesterday that all types are serializeable. Given the problem you just highlighted, this seems problematic!
----------------------------
fun get_text () : transaction string =
return "hello world"
fun generate_page () : transaction xbody =
text <- source "";
return
<xml>
<hr/>
<dyn signal={
x <- signal text;
return <xml> {[x]} </xml>
}/>
<button value="click me"
onclick={fn _ => s <- rpc (get_text ()); set text s }
/>
</xml>
table t : { Elem : serialized xbody }
fun add_page () : transaction unit =
page <- generate_page ();
dml(INSERT INTO t(Elem) VALUES ({[serialize page]}))
fun main () : transaction page =
current_pages <-
queryX (SELECT * FROM t) (fn row => deserialize row.T.Elem);
return <xml>
<body>
<button value="add page"
onclick={fn _ => rpc (add_page ())}/>
<hr/>
{current_pages}
</body>
</xml>
----------------------------
Running this page, clicking on "add page", and then refreshing gives an error in Firefox's developer console.
— Peter
Post by Peter Brottveit Bock
It seems to me that it's not possible to store xml in a database.
Is there any reason for this?
Storing it in a database is prone to XML/HTML injection (therefore the
general case is disallowed).
Right, that's true.  However, it shouldn't be a concern when only your
Ur/Web app accesses that database.
Still, overnight I thought of another issue: legitimate JavaScript code
within HTML fragments can become illegitimate across versions of your
Ur/Web app!  A global identifier may no longer exist, causing an
unbound-identifier exception when using HTML retrieved from the
database.  To me, this is the kiss of death, reminding me why this
feature deserves to be left out.
_______________________________________________
Ur mailing list
http://www.impredicative.com/cgi-bin/mailman/listinfo/ur
_______________________________________________
Ur mailing list
http://www.impredicative.com/cgi-bin/mailman/listinfo/ur
Loading...