From 80eed483159a36ba734e3940aced2d8e8425dc1b Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 18 Apr 2018 17:30:02 +0200 Subject: [PATCH] Fix solidity var extraction. was using the type property. now using stateVariable && storageLocation --- remix-solidity/src/decoder/decodeInfo.js | 7 ++-- .../src/decoder/internalCallTree.js | 9 +++- remix-solidity/src/decoder/stateDecoder.js | 2 +- remix-solidity/src/decoder/types/util.js | 13 +++++- remix-solidity/test/decoder/decodeInfo.js | 41 ++++++++++--------- 5 files changed, 45 insertions(+), 27 deletions(-) diff --git a/remix-solidity/src/decoder/decodeInfo.js b/remix-solidity/src/decoder/decodeInfo.js index 417fa85cce..e65f46ec28 100644 --- a/remix-solidity/src/decoder/decodeInfo.js +++ b/remix-solidity/src/decoder/decodeInfo.js @@ -190,7 +190,7 @@ function struct (type, stateDefinitions, contractName, location) { if (!location) { location = match[2].trim() } - var memberDetails = getStructMembers(match[1], stateDefinitions, contractName) // type is used to extract the ast struct definition + var memberDetails = getStructMembers(match[1], stateDefinitions, contractName, location) // type is used to extract the ast struct definition if (!memberDetails) return null return new StructType(memberDetails, location, match[1]) } else { @@ -230,9 +230,10 @@ function getEnum (type, stateDefinitions, contractName) { * @param {String} typeName - name of the struct type (e.g struct ) * @param {Object} stateDefinitions - all state definition given by the AST (including struct and enum type declaration) for all contracts * @param {String} contractName - contract the @args typeName belongs to + * @param {String} location - location of the data (storage ref| storage pointer| memory| calldata) * @return {Array} containing all members of the current struct type */ -function getStructMembers (type, stateDefinitions, contractName) { +function getStructMembers (type, stateDefinitions, contractName, location) { var split = type.split('.') if (!split.length) { type = contractName + '.' + type @@ -243,7 +244,7 @@ function getStructMembers (type, stateDefinitions, contractName) { if (state) { for (var dec of state.stateDefinitions) { if (dec.name === 'StructDefinition' && type === contractName + '.' + dec.attributes.name) { - var offsets = computeOffsets(dec.children, stateDefinitions, contractName) + var offsets = computeOffsets(dec.children, stateDefinitions, contractName, location) if (!offsets) { return null } diff --git a/remix-solidity/src/decoder/internalCallTree.js b/remix-solidity/src/decoder/internalCallTree.js index 590a96de07..1f2559c0d8 100644 --- a/remix-solidity/src/decoder/internalCallTree.js +++ b/remix-solidity/src/decoder/internalCallTree.js @@ -6,6 +6,7 @@ var EventManager = remixLib.EventManager var decodeInfo = require('./decodeInfo') var util = remixLib.util var traceHelper = remixLib.helpers.trace +var typesUtil = require('./types/util.js') /** * Tree representing internal jump into function. @@ -189,9 +190,11 @@ function includeVariableDeclaration (tree, step, sourceLocation, scopeId, newLoc tree.solidityProxy.contractNameAt(step, (error, contractName) => { // cached if (!error) { var states = tree.solidityProxy.extractStatesDefinitions() + var location = typesUtil.extractLocationFromAstVariable(variableDeclaration) + location = location === 'default' ? 'storage' : location tree.scopes[scopeId].locals[variableDeclaration.attributes.name] = { name: variableDeclaration.attributes.name, - type: decodeInfo.parseType(variableDeclaration.attributes.type, states, contractName), + type: decodeInfo.parseType(variableDeclaration.attributes.type, states, contractName, location), stackDepth: stack.length, sourceLocation: sourceLocation } @@ -274,9 +277,11 @@ function addParams (parameterList, tree, scopeId, states, contractName, sourceLo var param = parameterList.children[inputParam] var stackDepth = stackLength + (dir * stackPosition) if (stackDepth >= 0) { + var location = typesUtil.extractLocationFromAstVariable(param) + location = location === 'default' ? 'memory' : location tree.scopes[scopeId].locals[param.attributes.name] = { name: param.attributes.name, - type: decodeInfo.parseType(param.attributes.type, states, contractName), + type: decodeInfo.parseType(param.attributes.type, states, contractName, location), stackDepth: stackDepth, sourceLocation: sourceLocation } diff --git a/remix-solidity/src/decoder/stateDecoder.js b/remix-solidity/src/decoder/stateDecoder.js index a15110c8ac..43baa32225 100644 --- a/remix-solidity/src/decoder/stateDecoder.js +++ b/remix-solidity/src/decoder/stateDecoder.js @@ -40,7 +40,7 @@ function extractStateVariables (contractName, sourcesList) { return [] } var types = states[contractName].stateVariables - var offsets = decodeInfo.computeOffsets(types, states, contractName) + var offsets = decodeInfo.computeOffsets(types, states, contractName, 'storage') if (!offsets) { return [] // TODO should maybe return an error } diff --git a/remix-solidity/src/decoder/types/util.js b/remix-solidity/src/decoder/types/util.js index 35918aedb9..c7d8503b9e 100644 --- a/remix-solidity/src/decoder/types/util.js +++ b/remix-solidity/src/decoder/types/util.js @@ -11,7 +11,8 @@ module.exports = { add: add, extractLocation: extractLocation, removeLocation: removeLocation, - normalizeHex: normalizeHex + normalizeHex: normalizeHex, + extractLocationFromAstVariable: extractLocationFromAstVariable } function decodeIntFromHex (value, byteLength, signed) { @@ -100,6 +101,16 @@ function extractLocation (type) { } } +function extractLocationFromAstVariable (node) { + if (node.attributes.storageLocation !== 'default') { + return node.attributes.storageLocation + } else if (node.attributes.stateVariable) { + return 'storage' + } else { + return 'default' // local variables => storage, function parameters & return values => memory, state => storage + } +} + function normalizeHex (hex) { hex = hex.replace('0x', '') if (hex.length < 64) { diff --git a/remix-solidity/test/decoder/decodeInfo.js b/remix-solidity/test/decoder/decodeInfo.js index 3a23f0346a..4e100f2b79 100644 --- a/remix-solidity/test/decoder/decodeInfo.js +++ b/remix-solidity/test/decoder/decodeInfo.js @@ -8,6 +8,7 @@ var contracts = require('./contracts/miscContracts') var simplecontracts = require('./contracts/simpleContract') var remixLib = require('remix-lib') var compilerInput = remixLib.helpers.compiler.compilerInput +var util = require('../../src/decoder/types/util') tape('solidity', function (t) { t.test('astHelper, decodeInfo', function (st) { @@ -17,31 +18,31 @@ tape('solidity', function (t) { var state = astHelper.extractStateDefinitions('test.sol:contractUint', output.sources) var states = astHelper.extractStatesDefinitions(output.sources) var stateDef = state.stateDefinitions - var parsedType = decodeInfo.parseType(stateDef[0].attributes.type, states, 'contractUint') + var parsedType = decodeInfo.parseType(stateDef[0].attributes.type, states, 'contractUint', util.extractLocationFromAstVariable(stateDef[0])) checkDecodeInfo(st, parsedType, 1, 1, 'uint8') - parsedType = decodeInfo.parseType(stateDef[2].attributes.type, states, 'contractUint') + parsedType = decodeInfo.parseType(stateDef[2].attributes.type, states, 'contractUint', util.extractLocationFromAstVariable(stateDef[2])) checkDecodeInfo(st, parsedType, 1, 32, 'uint256') - parsedType = decodeInfo.parseType(stateDef[3].attributes.type, states, 'contractUint') + parsedType = decodeInfo.parseType(stateDef[3].attributes.type, states, 'contractUint', util.extractLocationFromAstVariable(stateDef[3])) checkDecodeInfo(st, parsedType, 1, 32, 'uint256') - parsedType = decodeInfo.parseType(stateDef[4].attributes.type, states, 'contractUint') + parsedType = decodeInfo.parseType(stateDef[4].attributes.type, states, 'contractUint', util.extractLocationFromAstVariable(stateDef[4])) checkDecodeInfo(st, parsedType, 1, 16, 'bytes16') state = astHelper.extractStateDefinitions('test.sol:contractStructAndArray', output.sources) stateDef = state.stateDefinitions - parsedType = decodeInfo.parseType(stateDef[1].attributes.type, states, 'contractStructAndArray') + parsedType = decodeInfo.parseType(stateDef[1].attributes.type, states, 'contractStructAndArray', util.extractLocationFromAstVariable(stateDef[1])) checkDecodeInfo(st, parsedType, 2, 32, 'struct contractStructAndArray.structDef') - parsedType = decodeInfo.parseType(stateDef[2].attributes.type, states, 'contractStructAndArray') + parsedType = decodeInfo.parseType(stateDef[2].attributes.type, states, 'contractStructAndArray', util.extractLocationFromAstVariable(stateDef[2])) checkDecodeInfo(st, parsedType, 6, 32, 'struct contractStructAndArray.structDef[3]') - parsedType = decodeInfo.parseType(stateDef[3].attributes.type, states, 'contractStructAndArray') + parsedType = decodeInfo.parseType(stateDef[3].attributes.type, states, 'contractStructAndArray', util.extractLocationFromAstVariable(stateDef[3])) checkDecodeInfo(st, parsedType, 2, 32, 'bytes12[4]') state = astHelper.extractStateDefinitions('test.sol:contractArray', output.sources) stateDef = state.stateDefinitions - parsedType = decodeInfo.parseType(stateDef[0].attributes.type, states, 'contractArray') + parsedType = decodeInfo.parseType(stateDef[0].attributes.type, states, 'contractArray', util.extractLocationFromAstVariable(stateDef[0])) checkDecodeInfo(st, parsedType, 1, 32, 'uint32[5]') - parsedType = decodeInfo.parseType(stateDef[1].attributes.type, states, 'contractArray') + parsedType = decodeInfo.parseType(stateDef[1].attributes.type, states, 'contractArray', util.extractLocationFromAstVariable(stateDef[1])) checkDecodeInfo(st, parsedType, 1, 32, 'int8[]') - parsedType = decodeInfo.parseType(stateDef[2].attributes.type, states, 'contractArray') + parsedType = decodeInfo.parseType(stateDef[2].attributes.type, states, 'contractArray', util.extractLocationFromAstVariable(stateDef[2])) checkDecodeInfo(st, parsedType, 4, 32, 'int16[][3][][4]') state = astHelper.extractStateDefinitions('test.sol:contractEnum', output.sources) @@ -51,17 +52,17 @@ tape('solidity', function (t) { state = astHelper.extractStateDefinitions('test.sol:contractSmallVariable', output.sources) stateDef = state.stateDefinitions - parsedType = decodeInfo.parseType(stateDef[0].attributes.type, states, 'contractSmallVariable') + parsedType = decodeInfo.parseType(stateDef[0].attributes.type, states, 'contractSmallVariable', util.extractLocationFromAstVariable(stateDef[0])) checkDecodeInfo(st, parsedType, 1, 1, 'int8') - parsedType = decodeInfo.parseType(stateDef[1].attributes.type, states, 'contractSmallVariable') + parsedType = decodeInfo.parseType(stateDef[1].attributes.type, states, 'contractSmallVariable', util.extractLocationFromAstVariable(stateDef[1])) checkDecodeInfo(st, parsedType, 1, 1, 'uint8') - parsedType = decodeInfo.parseType(stateDef[2].attributes.type, states, 'contractSmallVariable') + parsedType = decodeInfo.parseType(stateDef[2].attributes.type, states, 'contractSmallVariable', util.extractLocationFromAstVariable(stateDef[2])) checkDecodeInfo(st, parsedType, 1, 2, 'uint16') - parsedType = decodeInfo.parseType(stateDef[3].attributes.type, states, 'contractSmallVariable') + parsedType = decodeInfo.parseType(stateDef[3].attributes.type, states, 'contractSmallVariable', util.extractLocationFromAstVariable(stateDef[3])) checkDecodeInfo(st, parsedType, 1, 4, 'int32') - parsedType = decodeInfo.parseType(stateDef[4].attributes.type, states, 'contractSmallVariable') + parsedType = decodeInfo.parseType(stateDef[4].attributes.type, states, 'contractSmallVariable', util.extractLocationFromAstVariable(stateDef[4])) checkDecodeInfo(st, parsedType, 1, 32, 'uint256') - parsedType = decodeInfo.parseType(stateDef[5].attributes.type, states, 'contractSmallVariable') + parsedType = decodeInfo.parseType(stateDef[5].attributes.type, states, 'contractSmallVariable', util.extractLocationFromAstVariable(stateDef[5])) checkDecodeInfo(st, parsedType, 1, 2, 'int16') output = compiler.compileStandardWrapper(compilerInput(simplecontracts)) @@ -70,16 +71,16 @@ tape('solidity', function (t) { state = astHelper.extractStateDefinitions('test.sol:simpleContract', output.sources) states = astHelper.extractStatesDefinitions(output.sources) stateDef = state.stateDefinitions - parsedType = decodeInfo.parseType(stateDef[2].attributes.type, states, 'simpleContract') + parsedType = decodeInfo.parseType(stateDef[2].attributes.type, states, 'simpleContract', util.extractLocationFromAstVariable(stateDef[2])) checkDecodeInfo(st, parsedType, 2, 32, 'struct simpleContract.structDef') - parsedType = decodeInfo.parseType(stateDef[3].attributes.type, states, 'simpleContract') + parsedType = decodeInfo.parseType(stateDef[3].attributes.type, states, 'simpleContract', util.extractLocationFromAstVariable(stateDef[3])) checkDecodeInfo(st, parsedType, 6, 32, 'struct simpleContract.structDef[3]') - parsedType = decodeInfo.parseType(stateDef[4].attributes.type, states, 'simpleContract') + parsedType = decodeInfo.parseType(stateDef[4].attributes.type, states, 'simpleContract', util.extractLocationFromAstVariable(stateDef[4])) checkDecodeInfo(st, parsedType, 1, 1, 'enum') state = astHelper.extractStateDefinitions('test.sol:test2', output.sources) stateDef = state.stateDefinitions - parsedType = decodeInfo.parseType(stateDef[0].attributes.type, states, 'test1') + parsedType = decodeInfo.parseType(stateDef[0].attributes.type, states, 'test1', util.extractLocationFromAstVariable(stateDef[0])) checkDecodeInfo(st, parsedType, 0, 32, 'struct test1.str') state = stateDecoder.extractStateVariables('test.sol:test2', output.sources)