[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: [tor-bugs] #16990 [Tor Browser]: Circuit visualizer stops working after some time
#16990: Circuit visualizer stops working after some time
-------------------------------------------------+-------------------------
Reporter: cypherpunks | Owner: tbb-
Type: defect | team
Priority: Medium | Status:
Component: Tor Browser | assigned
Severity: Normal | Milestone:
Keywords: tbb-torbutton, tbb-circuit-display, | Version:
TorBrowserTeam201602 | Resolution:
Parent ID: | Actual Points:
Sponsor: | Points:
-------------------------------------------------+-------------------------
Comment (by cypherpunks):
I bring news, everyone!
Bad news: the bug is present in 5.5 as well.
Worse news: Tor project programmers apparently can't write parsers for
their own protocols.
Better news: I think I discovered at least one trigger for this bug.
I you don't want me to spoil your bug hunting, then just have this and go
dig at the code:
{{{
[01-29 09:48:25] Torbutton INFO: controlPort << getinfo circuit-status
[01-29 09:48:25] Torbutton INFO: controlPort >> 250+circuit-status=
243 BUILT $xxxxxx~nnnn,$xxxxxx~nnnn,$xxxxxx~nnnn BUNCH=OF KEY=VALUE
PAIRS=HERE
249 BUILT $xxxxxx~nnnn,$xxxxxx~nnnn,$xxxxxx~nnnn BUNCH=OF KEY=VALUE
PAIRS=HERE
247 BUILT $xxxxxx~nnnn,$xxxxxx~nnnn,$xxxxxx~nnnn BUNCH=OF KEY=VALUE
PAIRS=HERE
248 BUILT $xxxxxx~nnnn,$xxxxxx~nnnn,$xxxxxx~nnnn BUNCH=OF KEY=VALUE
PAIRS=HERE
250 BUILT $xxxxxx~nnnn BUNCH=OF KEY=VALUE PAIRS=HERE
}}}
I found that in my logs sometime after I noticed that the display was
gone. Why, yes those are 2 complete log messages, I didn't fuck up my
copypaste. You are right though, the second looks incomplete. Aaaand now
you see it, yes it starts and ends with 250.
This is the last message in the logs from the circuit display controller.
It went silent after this.
I had some time yesterday so I looked at the code. Narrating my
adventures would take too much so I'm just going to paste a diff with the
notes I took while reading. I point at a few places where I think bugs
exist; some of the comments are there just to keep track of the lovely
chained chains of functional filigrane arthuredelstein seems so infatuated
with (I understand you arthur, I like functional programming too, but man,
this is javascript, you know, it's kinda disgusting), so breadcrumbs
basically; also I comment on a couple of unrelated issues. All my
comments are prefixed with "punk:". The diff is against Torbutton as
shipped in 5.5, so 1.9.4.3.
Notice that I didn't live-debug the code, just read, so take what I say
with a boulder of salt.
{{{
--- a/torbutton/modules/tor-control-port.js
+++ b/torbutton/modules/tor-control-port.js
@@ -113,7 +113,10 @@ io.asyncSocket = function (host, port, o
let totalString = pendingWrites.join("");
try {
outputStream.write(totalString, totalString.length);
- log("controlPort << " + aString + "\n");
+ // punk: unrelated: for Firefox's console output,
log()
+ // will write each message in a separate line; for
stderr
+ // output, log() already appends '\n'
+ log("controlPort << " + aString.trim());
} catch (err) {
onError(err);
}
@@ -162,6 +165,21 @@ io.onLineFromOnMessage = function (onMes
// Add to the list of pending lines.
pendingLines.push(line);
// If line is the last in a message, then pass on the full multiline
message.
+ //
+ // punk: bug: this will cut the message short; it happens when one
the
+ // reply lines starts with the same 3 digits as the first one; in the
case
+ // of a successful "circuit-status" command, this happens when one of
the
+ // circuits in the reply has a circuit id of 250
+ //
+ // punk: bug: "pendingLines" can grow indefinetely if the lines
pushed into
+ // it do not align with the expected pattern: think what happens if
the
+ // first line pushed is ".", as could happen thanks to the other bug
just
+ // mentioned; this effectively disables the whole control-port
dispatcher
+ // contraption: no more messages will be received through this
controller
+ //
+ // -> how dangerous is this? what else is this controller used for?
+ //
+ // -> apparently nothing else; good
if (line.match(/^\d\d\d /) &&
(pendingLines.length === 1 ||
pendingLines[0].substring(0,3) === line.substring(0,3))) {
@@ -218,6 +236,21 @@ io.matchRepliesToCommands = function (as
};
// Watch for responses (replies or error messages)
dispatcher.addCallback(/^[245]\d\d/, function (message) {
+ // punk: bug: underflow if the callback triggers before the
sendCommand()
+ // in the following Promise is called (and, therefore, a triple is
pushed
+ // into "commandQueue")
+ //
+ // -> wait! apparently this is not actually an error (wat?):
[].shift()
+ // just returns undefined
+ //
+ // -> but then the _assignment_ fails: throws TypeError
+ //
+ // -> this may be happening in the case of the circuit display fuck-
up: the
+ // reply message is cut short, but the rest of the message (some
circuit
+ // status lines and then '.' and then '250 OK') will still be
delivered by
+ // Firefox through the socket, will be received by the smattering of
+ // chained funclets, and could then be made into a new message that
will be
+ // passed into this function
let [command, replyCallback, errorCallback] = commandQueue.shift();
if (message.match(/^2/) && replyCallback) replyCallback(message);
if (message.match(/^[45]/) && errorCallback) {
@@ -273,6 +306,9 @@ io.controlSocket = function (host, port,
// ## utils
// A namespace for utility functions
+//
+// punk: unrelated: why the fuck are these here? there's even a
"utils.js" over
+// there...
let utils = utils || {};
// __utils.identity(x)__.
@@ -398,6 +434,7 @@ info.keyValueStringsFromMessage = utils.
// and applies transformFunction to each line.
info.applyPerLine = function (transformFunction) {
return function (text) {
+ // punk: text is null, null.trim() throws TypeError
return utils.splitLines(text.trim()).map(transformFunction);
};
};
@@ -433,6 +470,7 @@ info.routerStatusParser = function (valu
// __info.circuitStatusParser(line)__.
// Parse the output of a circuit status line.
info.circuitStatusParser = function (line) {
+ // punk: unrelated: "circuit" here is called "path" in the spec
let data = utils.listMapData(line, ["id","status","circuit"]),
circuit = data.circuit;
// Parse out the individual circuit IDs and names.
@@ -500,11 +538,13 @@ info.getParser = function(key) {
info.stringToValue = function (string) {
// key should look something like `250+circuit-status=` or `250
-circuit-status=...`
// or `250 circuit-status=...`
- let matchForKey = string.match(/^250[ +-](.+?)=/),
+ let matchForKey = string.match(/^250[ \+-](.+?)=/),
key = matchForKey ? matchForKey[1] : null;
if (key === null) return null;
// matchResult finds a single-line result for `250-` or `250 `,
// or a multi-line one for `250+`.
+ //
+ // punk: won't match any of these
let matchResult = string.match(/^250[ -].+?=(.*)$/) ||
string.match(/^250\+.+?=([\s\S]*?)^\.$/m),
// Retrieve the captured group (the text of the value in the key-
value pair)
@@ -521,6 +561,9 @@ info.stringToValue = function (string) {
// __info.getMultipleResponseValues(message)__.
// Process multiple responses to a GETINFO or GETCONF request.
info.getMultipleResponseValues = function (message) {
+ // punk: keyValueStringsFromMessage() won't match the message, the
result
+ // will be an empty array, so all thre rest is a no-op, and the return
value
+ // is also an empty array
return info.keyValueStringsFromMessage(message)
.map(info.stringToValue)
.filter(utils.identity);
@@ -534,6 +577,12 @@ info.getInfo = function (aControlSocket,
}
return aControlSocket
.sendCommand("getinfo " + key)
+ // punk: overflow; getMultipleResponseValues returns an empty array
+ //
+ // -> lol, apparently an overflow is not an error in this ridiculous
+ // language, the result is just undefined
+ //
+ // -> so then info.getInfo returns undefined
.then(response => info.getMultipleResponseValues(response)[0]);
};
@@ -639,4 +688,3 @@ let controller = function (host, port, p
// Export the controller function for external use.
var EXPORTED_SYMBOLS = ["controller"];
-
--- a/torbutton/chrome/content/tor-circuit-display.js
+++ b/torbutton/chrome/content/tor-circuit-display.js
@@ -113,6 +113,7 @@ let nodeDataForCircuit = function* (cont
// Returns the circuit status for the circuit with the given ID.
let getCircuitStatusByID = function* (aController, circuitID) {
let circuitStatuses = yield aController.getInfo("circuit-status");
+ // punk: this test fails: circuitStatuses is undefined
if (circuitStatuses) {
for (let circuitStatus of circuitStatuses) {
if (circuitStatus.id === circuitID) {
@@ -120,6 +121,7 @@ let getCircuitStatusByID = function* (aC
}
}
}
+ // punk: so null is returned
return null;
};
@@ -139,16 +141,20 @@ let collectIsolationData = function (aCo
if (!knownCircuitIDs[streamEvent.CircuitID]) {
logger.eclog(3, "streamEvent.CircuitID: " +
streamEvent.CircuitID);
knownCircuitIDs[streamEvent.CircuitID] = true;
+ // punk: circuitStatus is null, so credentials is null as well
let circuitStatus = yield getCircuitStatusByID(aController,
streamEvent.CircuitID),
credentials = circuitStatus ?
(trimQuotes(circuitStatus.SOCKS_USERNAME) +
"|" +
trimQuotes(circuitStatus.SOCKS_PASSWORD)) :
null;
+ // punk: so the update doesn't happen
if (credentials) {
let nodeData = yield nodeDataForCircuit(aController,
circuitStatus);
credentialsToNodeDataMap[credentials] = nodeData;
updateUI();
}
+ // punk: but then nothing else, no other visible breakage...
shouldn't
+ // you be screaming something here?
}
}).then(null, Cu.reportError));
};
@@ -356,4 +362,3 @@ return setupDisplay;
// Finish createTorCircuitDisplay()
})();
-
}}}
Take-away points:
1. The control protocol doesn't have a formal grammar (no, control-
spec.txt doesn't qualify, it, at the very least, is incomplete). Result:
objectively-correct parsers can't be generated.
2. Tor and the controller in Torbutton do not speak the same protocol.
Expect more breakage.
3. Compartmentalising controllers is a good idea. Keep doing that.
4. JavaScript is ridonkeylous. Keep away.
--
Ticket URL: <https://trac.torproject.org/projects/tor/ticket/16990#comment:28>
Tor Bug Tracker & Wiki <https://trac.torproject.org/>
The Tor Project: anonymity online
_______________________________________________
tor-bugs mailing list
tor-bugs@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-bugs