aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Adam Chlipala <adam@chlipala.net>2013-12-27 12:10:03 -0500
committerGravatar Adam Chlipala <adam@chlipala.net>2013-12-27 12:10:03 -0500
commitd99d4f09bb2947a09eb6e1c12057bd805dac070c (patch)
tree85f0265a4778128dee390ef80d943cc6c5b0669f
parentaea9e6db8a7a72dd555913a38cb893d247c3c09e (diff)
Raise exception when recv()ing from someone else's channel; improve setting of client ID in RPCs
-rw-r--r--lib/js/urweb.js2
-rw-r--r--src/c/urweb.c48
-rw-r--r--tests/channelThief.ur32
-rw-r--r--tests/channelThief.urp5
-rw-r--r--tests/channelThief.urs1
5 files changed, 62 insertions, 26 deletions
diff --git a/lib/js/urweb.js b/lib/js/urweb.js
index e211d318..6830945a 100644
--- a/lib/js/urweb.js
+++ b/lib/js/urweb.js
@@ -1575,7 +1575,7 @@ function rv(chn, parse, k) {
er("May not 'recv' in main thread of 'code' for <active>");
if (chn == null)
- return;
+ er("Client-side code tried to recv() from a channel belonging to a different page view.");
if (chn < 0)
whine("Out-of-bounds channel receive");
diff --git a/src/c/urweb.c b/src/c/urweb.c
index af5cc461..0265c67f 100644
--- a/src/c/urweb.c
+++ b/src/c/urweb.c
@@ -734,36 +734,34 @@ void uw_push_cleanup(uw_context ctx, void (*func)(void *), void *arg) {
char *uw_Basis_htmlifyString(uw_context, const char *);
void uw_login(uw_context ctx) {
- if (ctx->needs_push) {
- char *id_s, *pass_s;
+ char *id_s, *pass_s;
- if ((id_s = uw_Basis_requestHeader(ctx, "UrWeb-Client"))
- && (pass_s = uw_Basis_requestHeader(ctx, "UrWeb-Pass"))) {
- unsigned id = atoi(id_s);
- int pass = atoi(pass_s);
- client *c = find_client(id);
-
- if (c == NULL)
- uw_error(ctx, FATAL, "Unknown client ID in HTTP headers (%s, %s)", uw_Basis_htmlifyString(ctx, id_s), uw_Basis_htmlifyString(ctx, pass_s));
- else {
- use_client(c);
- ctx->client = c;
-
- if (c->mode != USED)
- uw_error(ctx, FATAL, "Stale client ID (%u) in subscription request", id);
- if (c->pass != pass)
- uw_error(ctx, FATAL, "Wrong client password (%u, %d) in subscription request", id, pass);
- }
- } else {
- client *c = new_client();
-
- if (c == NULL)
- uw_error(ctx, FATAL, "Limit exceeded on number of message-passing clients");
+ if ((id_s = uw_Basis_requestHeader(ctx, "UrWeb-Client"))
+ && (pass_s = uw_Basis_requestHeader(ctx, "UrWeb-Pass"))) {
+ unsigned id = atoi(id_s);
+ int pass = atoi(pass_s);
+ client *c = find_client(id);
+ if (c == NULL)
+ uw_error(ctx, FATAL, "Unknown client ID in HTTP headers (%s, %s)", uw_Basis_htmlifyString(ctx, id_s), uw_Basis_htmlifyString(ctx, pass_s));
+ else {
use_client(c);
- uw_copy_client_data(c->data, ctx->client_data);
ctx->client = c;
+
+ if (c->mode != USED)
+ uw_error(ctx, FATAL, "Stale client ID (%u) in subscription request", id);
+ if (c->pass != pass)
+ uw_error(ctx, FATAL, "Wrong client password (%u, %d) in subscription request", id, pass);
}
+ } else if (ctx->needs_push) {
+ client *c = new_client();
+
+ if (c == NULL)
+ uw_error(ctx, FATAL, "Limit exceeded on number of message-passing clients");
+
+ use_client(c);
+ uw_copy_client_data(c->data, ctx->client_data);
+ ctx->client = c;
}
}
diff --git a/tests/channelThief.ur b/tests/channelThief.ur
new file mode 100644
index 00000000..1893979a
--- /dev/null
+++ b/tests/channelThief.ur
@@ -0,0 +1,32 @@
+table t : { Ch : channel string }
+
+fun go () =
+ let
+ fun overwrite () =
+ dml (DELETE FROM t WHERE TRUE);
+ ch <- channel;
+ dml (INSERT INTO t (Ch) VALUES ({[ch]}));
+ return ch
+
+ fun retrieve () =
+ oneRowE1 (SELECT (t.Ch) FROM t)
+
+ fun transmit () =
+ ch <- retrieve ();
+ send ch "Test"
+
+ fun listenOn ch =
+ s <- recv ch;
+ alert s
+ in
+ ch <- overwrite ();
+ return <xml><body onload={listenOn ch}>
+ <button value="overwrite" onclick={fn _ => ch <- rpc (overwrite ()); listenOn ch}/>
+ <button value="retrieve" onclick={fn _ => ch <- rpc (retrieve ()); listenOn ch}/>
+ <button value="transmit" onclick={fn _ => rpc (transmit ())}/>
+ </body></xml>
+ end
+
+fun main () = return <xml><body>
+ <form><submit action={go}/></form>
+</body></xml>
diff --git a/tests/channelThief.urp b/tests/channelThief.urp
new file mode 100644
index 00000000..dee402d4
--- /dev/null
+++ b/tests/channelThief.urp
@@ -0,0 +1,5 @@
+database dbname=test
+sql channelThief.sql
+rewrite url ChannelThief/*
+
+channelThief
diff --git a/tests/channelThief.urs b/tests/channelThief.urs
new file mode 100644
index 00000000..6ac44e0b
--- /dev/null
+++ b/tests/channelThief.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page