Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
repl: ensure eval serialization does not throw
If an error is thrown during the readline `keypress` event, the state of
the streaming escape sequence decoder (added in
#1601) will become corrupted. This
will render the REPL (and possibly your whole terminal) completely
unusable. This can be triggered by an object with a custom `inspect`
method that throws.

This commit adds an extra try/catch around `self.writer` (which is
`util.inspect` by default).
  • Loading branch information
monsanto committed Jun 13, 2015
commit 2380c93a39e896da22992cf66acff9615ef592d8
8 changes: 7 additions & 1 deletion lib/repl.js
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,13 @@ function REPLServer(prompt,
// If we got any output - print it (if no error)
if (!e && (!self.ignoreUndefined || ret !== undefined)) {
self.context._ = ret;
self.outputStream.write(self.writer(ret) + '\n');
try {
var s = self.writer(ret);
} catch(e) {
process.domain.emit('error', e);
return;
}
self.outputStream.write(s + '\n');
}

// Display prompt again
Expand Down
51 changes: 51 additions & 0 deletions test/parallel/test-repl-inspect-throw.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
'use strict';
var assert = require('assert');
var common = require('../common');
var util = require('util');
var repl = require('repl');

// A stream to push an array into a REPL
function ArrayStream() {
this.run = function(data) {
var self = this;
data.forEach(function(line) {
self.emit('data', line + '\n');
});
};
}
util.inherits(ArrayStream, require('stream').Stream);
ArrayStream.prototype.readable = true;
ArrayStream.prototype.writable = true;
ArrayStream.prototype.resume = function() {};
ArrayStream.prototype.write = function() {};

var putIn = new ArrayStream();
var testMe = repl.start({
input: putIn,
output: putIn,
terminal: true
});

// Regression test: an exception raised during the 'keypress' event in readline
// would corrupt the state of the escape sequence decoder, rendering the REPL
// (and possibly your terminal) completely unusable.
//
// We can trigger this by triggering a throw inside util.inspect, which is used
// to print a string representation of what you evaluate in the REPL.
testMe.context.throwObj = {
inspect: function() {
throw new Error('inspect error');
}
};
testMe.context.reached = false;

// Exceptions for whatever reason do not reach the normal error handler after
// the inspect throw, but will work if run in another tick.
process.nextTick(function() {
assert(testMe.context.reached);
});

putIn.run([
'throwObj',
'reached = true'
]);