Skip to content

Altering Object.prototype.name breaks in the REPL #11614

Closed
@nem035

Description

@nem035
  • Version: Tested on all from 5.11.1 to 7.6.0.
  • Platform: Darwin 15.6.0 Darwin Kernel Version 15.6.0: Thu Sep 1 15:01:16 PDT 2016; root:xnu-3248.60.11~2/RELEASE_X86_64 x86_64
  • Subsystem: Util

Problematic code:

Object.prototype.name = "bug"
Object.prototype

Sample run:

screen shot 2017-02-28 at 12 17 35 pm

Code breaks in stylizeWithColor the following line.

Why?

Because we are printing a property, the call to stylizeWithColor passes 'name' as the styleType where 'name' style type is actually ignored.

These style types are stored in the plain object inspect.styles so the execution expects inspect.styles['name'] on the first line of stylizeWithColor to return undefined (since it is ignored) and not enter the if statement.

function stylizeWithColor(str, styleType) {
  var style = inspect.styles[styleType]; // <-- this should return `undefined`

  if (style) { // <-- this shouldn't happen
    return `\u001b[${inspect.colors[style][0]}m${str}` +
           `\u001b[${inspect.colors[style][1]}m`;
  } else {
    return str;
  }
}

However, since we added a "name" property on Object.prototype, inspect.styles['name'] doesn't find 'name' directly but does find it up the [[Prototype]] chain and actually returns the string"bug".

function stylizeWithColor(str, styleType) {
  var style = inspect.styles[styleType]; // <-- this returns "bug"` because it found it up the [[Prototype]] chain

  if (style) { // <-- // <-- this happens because "bug" is truthy
    return `\u001b[${inspect.colors[style][0]}m${str}` +
           `\u001b[${inspect.colors[style][1]}m`;
  } else {
    return str;
  }
}

This means that the code tries to execute inspect.colors["bug"][0], which gives undefined[0], and throws the error in the issue.

A funny consequence is that, if we make name equal to a color value used in inspect.colors, then the error wouldn't happen and the property name will be printed in that color.

screen shot 2017-02-28 at 10 30 52 pm

Proposed solution

Use an object not linked to Object.prototype for inspect.style.

const styles = {
  'special': 'cyan',
  'number': 'yellow',
  'boolean': 'yellow',
  'undefined': 'grey',
  'null': 'bold',
  'string': 'green',
  'symbol': 'green',
  'date': 'magenta',
  // "name": intentionally not styling
  'regexp': 'red'
};
inspect.styles = Object.assign(Object.create(null), styles);

If confirmed, I'd be happy to implement it.


Inspired by this StackOverflow question

Metadata

Metadata

Assignees

No one assigned

    Labels

    utilIssues and PRs related to the built-in util module.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions