embark-mythx/lib/srcmap.js
Sebastian Mueller d82bb67dbd Initial commit
2019-04-26 18:08:49 +02:00

119 lines
4.1 KiB
JavaScript

// Things involving the richer solc source map with its AST.
// We use this to filter out some MythX error messages.
//
'use strict';
const assert = require('assert');
const remixUtil = require('remix-lib/src/util');
const SourceMappingDecoder = require('../compat/remix-lib/sourceMappingDecoder.js');
const opcodes = require('remix-lib/src/code/opcodes');
module.exports = {
/**
* Return the VariableDeclaration AST node associated with instIndex
* if there is one. Otherwise return null.
* @param {sourceLocation} string - solc srcmap used to associate the instruction
* with an ast node
* @param {ast} - solc root AST for contract
* @return {AST node or null}
*
*/
isVariableDeclaration: function (srcmap, ast) {
const sourceMappingDecoder = new SourceMappingDecoder();
const sourceLocation = sourceMappingDecoder.decode(srcmap);
return sourceMappingDecoder.findNodeAtSourceLocation('VariableDeclaration',
sourceLocation, ast);
},
/**
* Return the true is AST node is a public array.
* @param {node} AST node - bytecode offset of instruction
* @return {boolean}
*
*/
isDynamicArray: function (node) {
// FIXME: do we want to check:
// constant: false
// storageLocation: 'default'
return (node.stateVariable &&
node.visibility === 'public' &&
node.typeName.nodeType === 'ArrayTypeName');
},
/**
* Takes a bytecode hexstring and returns a map indexed by offset
* that give the instruction number for that offset.
*
* @param {hexstr} string - bytecode hexstring
* @return {array mapping bytecode offset to an instruction number}
*
*/
makeOffset2InstNum: function(hexstr) {
const bytecode = remixUtil.hexToIntArray(hexstr);
const instMap = {};
let j = -1;
for (let i = 0; i < bytecode.length; i++) {
j++;
const opcode = opcodes(bytecode[i], true);
if (opcode.name.slice(0, 4) === 'PUSH') {
let length = bytecode[i] - 0x5f;
i += length;
}
instMap[i] = j;
}
return instMap;
},
// FIXME: seenIndices is not being used. Remove it?
/**
* @param {String} sourceMap - solc-type sourceMap
* @return {Set} a set containing the "file" indices seen in a sourceMap
*/
seenIndices: function(sourceMap) {
const seen = new Set();
const srcArray = sourceMap.split(';');
for (const src of srcArray) {
const fields = src.split(':');
if (fields.length >= 3) {
const index = fields[2];
// File index -1 means no file exists.
// Value '' means that the field is empty but present
// to be able to give a 4th value.
// Skip either of these.
if (index !== '-1' && index !== '') {
seen.add(index);
}
}
}
return seen;
},
// FIXME: this is just a stopgap measure.
// The caller in mythx should be fixed to we don't need this.
/**
* @param {String} sourceMap - solc-type sourceMap
* @return take sourceMap entries and turn them into file index 0
*/
zeroedSourceMap: function(sourceMap) {
const srcArray = sourceMap.split(';');
let modArray = [];
let indexSeen = -2;
for (const src of srcArray) {
const fields = src.split(':');
if (fields.length >= 3) {
const index = fields[2];
if (index !== '-1' && index !== '') {
if (indexSeen !== -2) {
assert(indexSeen === index,
`assuming only one index ${indexSeen} needs moving; saw ${index} as well`);
}
fields[2] = '0';
}
}
const modFields = fields.join(':');
modArray.push(modFields);
}
return modArray.join(';');
},
};