commit e9fc7e9e3becded38c87e92a864c44bcd68219c5 Author: Arthur Edelstein arthuredelstein@gmail.com Date: Fri Feb 5 17:38:42 2016 -0800
Bug 16690: Don't mishandle multiline commands
Also, when logging, don't show a bunch of extra newlines.
See https://trac.torproject.org/16990#comment:28 --- src/modules/tor-control-port.js | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/src/modules/tor-control-port.js b/src/modules/tor-control-port.js index c5010de..e1ee6bc 100644 --- a/src/modules/tor-control-port.js +++ b/src/modules/tor-control-port.js @@ -27,11 +27,11 @@ Cu.import("resource://gre/modules/Services.jsm"); // Logging function let log; if ((typeof console) !== "undefined") { - log = x => console.log(typeof(x) === "string" ? x : JSON.stringify(x)); + log = x => console.log(typeof(x) === "string" ? x.trimRight().replace(/\r\n/g, "\n") : JSON.stringify(x)); } else { let logger = Cc["@torproject.org/torbutton-logger;1"] .getService(Components.interfaces.nsISupports).wrappedJSObject; - log = x => logger.eclog(3, x); + log = x => logger.eclog(3, x.trimRight().replace(/\r\n/g, "\n")); }
// ### announce this file @@ -113,7 +113,7 @@ io.asyncSocket = function (host, port, onInputData, onError) { let totalString = pendingWrites.join(""); try { outputStream.write(totalString, totalString.length); - log("controlPort << " + aString + "\n"); + log("controlPort << " + totalString); } catch (err) { onError(err); } @@ -156,13 +156,26 @@ io.onDataFromOnLine = function (onLine) { // callback that expects individual lines. io.onLineFromOnMessage = function (onMessage) { // A private variable that stores the last unfinished line. - let pendingLines = []; + let pendingLines = [], + // A private variable to monitor whether we are receiving a multiline + // value, beginning with ###+ and ending with a single ".". + multilineValueInProgress = false; // Return a callback that expects individual lines. return function (line) { // Add to the list of pending lines. pendingLines.push(line); + // 'Multiline values' are possible. We avoid interrupting one by detecting it + // and waiting for a terminating "." on its own line. + // (See control-spec section 3.9 and https://trac.torproject.org/16990#comment:28 + if (line.match(/^\d\d\d+.+?=$/) && pendingLines.length === 1) { + multilineValueInProgress = true; + } + if (multilineValueInProgress && line.match(/^.$/)) { + multilineValueInProgress = false; + } // If line is the last in a message, then pass on the full multiline message. - if (line.match(/^\d\d\d /) && + if (!multilineValueInProgress && + line.match(/^\d\d\d /) && (pendingLines.length === 1 || pendingLines[0].substring(0,3) === line.substring(0,3))) { // Combine pending lines to form message.