From 19906c4262d8175602ac4ebb2c4e14ee8a9ce140 Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Thu, 31 Oct 2019 13:32:14 -0700 Subject: [PATCH] fix(slot): prevent crosstalk by tracking inbound vs. outbound slots --- lib/captp.js | 10 ++++++---- test/crosstalk.js | 48 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 test/crosstalk.js diff --git a/lib/captp.js b/lib/captp.js index 161b03f93f1..0e185f963b5 100644 --- a/lib/captp.js +++ b/lib/captp.js @@ -34,7 +34,7 @@ export function makeCapTP(ourId, send, bootstrapObj = undefined) { if (Promise.resolve(val) === val) { lastPromiseID += 1; const promiseID = lastPromiseID; - slot = `p${promiseID}`; + slot = `p+${promiseID}`; val.then( res => send({ @@ -52,7 +52,7 @@ export function makeCapTP(ourId, send, bootstrapObj = undefined) { } else { lastExportID += 1; const exportID = lastExportID; - slot = `o${exportID}`; + slot = `o+${exportID}`; } valToSlot.set(val, slot); slotToVal.set(slot, val); @@ -114,8 +114,10 @@ export function makeCapTP(ourId, send, bootstrapObj = undefined) { } function unserializeSlot(data, slots) { - const slot = slots[Nat(data.index)]; + const theirSlot = slots[Nat(data.index)]; let val; + const otherDir = theirSlot[1] === '+' ? '-' : '+'; + const slot = `${theirSlot[0]}${otherDir}${theirSlot.slice(2)}`; if (!slotToVal.has(slot)) { // Make a new handled promise for the slot. const pr = makeRemote(slot); @@ -127,7 +129,7 @@ export function makeCapTP(ourId, send, bootstrapObj = undefined) { val = presence; } else { // A new promise - imports.set(Number(slot.slice(1)), pr); + imports.set(Number(slot.slice(2)), pr); val = pr.p; } slotToVal.set(slot, val); diff --git a/test/crosstalk.js b/test/crosstalk.js new file mode 100644 index 00000000000..1e692ab3f6a --- /dev/null +++ b/test/crosstalk.js @@ -0,0 +1,48 @@ +import { test } from 'tape-promise/tape'; +import { harden, makeCapTP, E } from '../lib/captp'; + +test('prevent crosstalk', async t => { + try { + const debug = false; + let rightDispatch; + const { dispatch: leftDispatch, getBootstrap: leftBootstrap } = makeCapTP( + 'left', + obj => { + if (debug) { + console.log('toRight', obj); + } + rightDispatch(obj); + }, + ); + ({ dispatch: rightDispatch } = makeCapTP( + 'right', + obj => { + if (debug) { + console.log('toLeft', obj); + } + leftDispatch(obj); + }, + harden({ + isSide(objP, side) { + return E(objP).side().then(s => t.equal(s, side, `obj.side() is ${side}`)); + }, + side() { + return 'right'; + }, + }) + )); + const rightRef = leftBootstrap(); + + await E(rightRef).isSide(rightRef, 'right'); + const leftRef = harden({ + side() { + return 'left'; + }, + }); + await E(rightRef).isSide(leftRef, 'left'); + } catch (e) { + t.isNot(e, e, 'unexpected exception'); + } finally { + t.end(); + } +});