mirror of
https://github.com/embarklabs/embark-mythx.git
synced 2025-02-09 17:13:52 +00:00
119 lines
4.1 KiB
JavaScript
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(';');
|
|
},
|
|
};
|