|
|
@ -13,7 +13,12 @@ class Injector { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
_getInjectable(fileName, hash, type){ |
|
|
|
_getInjectable(fileName, hash, type){ |
|
|
|
return `${this._getMethodIdentifier(fileName)}(${hash}); /* ${type} */ \n`; |
|
|
|
switch(type){ |
|
|
|
|
|
|
|
case 'logicalOR': |
|
|
|
|
|
|
|
return ` && ${this._getTrueMethodIdentifier(fileName)}(${hash}))`; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
return `${this._getDefaultMethodIdentifier(fileName)}(${hash}); /* ${type} */ \n`; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
_getHash(fileName) { |
|
|
|
_getHash(fileName) { |
|
|
@ -21,10 +26,16 @@ class Injector { |
|
|
|
return web3Utils.keccak256(`${fileName}:${this.hashCounter}`); |
|
|
|
return web3Utils.keccak256(`${fileName}:${this.hashCounter}`); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
_getMethodIdentifier(fileName){ |
|
|
|
// Method returns void
|
|
|
|
|
|
|
|
_getDefaultMethodIdentifier(fileName){ |
|
|
|
return `coverage_${web3Utils.keccak256(fileName).slice(0,10)}` |
|
|
|
return `coverage_${web3Utils.keccak256(fileName).slice(0,10)}` |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Method returns boolean true
|
|
|
|
|
|
|
|
_getTrueMethodIdentifier(fileName){ |
|
|
|
|
|
|
|
return `coverage_true${web3Utils.keccak256(fileName).slice(0,10)}` |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
_getInjectionComponents(contract, injectionPoint, fileName, type){ |
|
|
|
_getInjectionComponents(contract, injectionPoint, fileName, type){ |
|
|
|
const { start, end } = this._split(contract, injectionPoint); |
|
|
|
const { start, end } = this._split(contract, injectionPoint); |
|
|
|
const hash = this._getHash(fileName) |
|
|
|
const hash = this._getHash(fileName) |
|
|
@ -39,17 +50,29 @@ class Injector { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Generates a solidity statement injection. Declared once per fn. |
|
|
|
* Generates a solidity statement injection defining a method |
|
|
|
* Definition is the same for every fn in file. |
|
|
|
* *which returns void* to pass instrumentation hash to. |
|
|
|
* @param {String} fileName |
|
|
|
* @param {String} fileName |
|
|
|
* @return {String} ex: bytes32[1] memory _sc_82e0891 |
|
|
|
* @return {String} ex: bytes32[1] memory _sc_82e0891 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
_getHashMethodDefinition(fileName){ |
|
|
|
_getDefaultMethodDefinition(fileName){ |
|
|
|
const hash = web3Utils.keccak256(fileName).slice(0,10); |
|
|
|
const hash = web3Utils.keccak256(fileName).slice(0,10); |
|
|
|
const method = this._getMethodIdentifier(fileName); |
|
|
|
const method = this._getDefaultMethodIdentifier(fileName); |
|
|
|
return `\nfunction ${method}(bytes32 c__${hash}) public pure {}\n`; |
|
|
|
return `\nfunction ${method}(bytes32 c__${hash}) public pure {}\n`; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Generates a solidity statement injection defining a method |
|
|
|
|
|
|
|
* *which returns boolean true* to pass instrumentation hash to. |
|
|
|
|
|
|
|
* @param {String} fileName |
|
|
|
|
|
|
|
* @return {String} ex: bytes32[1] memory _sc_82e0891 |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
_getTrueMethodDefinition(fileName){ |
|
|
|
|
|
|
|
const hash = web3Utils.keccak256(fileName).slice(0,10); |
|
|
|
|
|
|
|
const method = this._getTrueMethodIdentifier(fileName); |
|
|
|
|
|
|
|
return `\nfunction ${method}(bytes32 c__${hash}) public pure returns (bool){ return true; }\n`; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
injectLine(contract, fileName, injectionPoint, injection, instrumentation){ |
|
|
|
injectLine(contract, fileName, injectionPoint, injection, instrumentation){ |
|
|
|
const type = 'line'; |
|
|
|
const type = 'line'; |
|
|
|
const { start, end } = this._split(contract, injectionPoint); |
|
|
|
const { start, end } = this._split(contract, injectionPoint); |
|
|
@ -196,7 +219,37 @@ class Injector { |
|
|
|
injectHashMethod(contract, fileName, injectionPoint, injection, instrumentation){ |
|
|
|
injectHashMethod(contract, fileName, injectionPoint, injection, instrumentation){ |
|
|
|
const start = contract.instrumented.slice(0, injectionPoint); |
|
|
|
const start = contract.instrumented.slice(0, injectionPoint); |
|
|
|
const end = contract.instrumented.slice(injectionPoint); |
|
|
|
const end = contract.instrumented.slice(injectionPoint); |
|
|
|
contract.instrumented = `${start}${this._getHashMethodDefinition(fileName)}${end}`; |
|
|
|
contract.instrumented = `${start}` + |
|
|
|
|
|
|
|
`${this._getDefaultMethodDefinition(fileName)}` + |
|
|
|
|
|
|
|
`${this._getTrueMethodDefinition(fileName)}` + |
|
|
|
|
|
|
|
`${end}`; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
injectOpenParen(contract, fileName, injectionPoint, injection, instrumentation){ |
|
|
|
|
|
|
|
const start = contract.instrumented.slice(0, injectionPoint); |
|
|
|
|
|
|
|
const end = contract.instrumented.slice(injectionPoint); |
|
|
|
|
|
|
|
contract.instrumented = `${start}(${end}`; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
injectLogicalOR(contract, fileName, injectionPoint, injection, instrumentation){ |
|
|
|
|
|
|
|
const type = 'logicalOR'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const { |
|
|
|
|
|
|
|
start, |
|
|
|
|
|
|
|
end, |
|
|
|
|
|
|
|
hash, |
|
|
|
|
|
|
|
injectable |
|
|
|
|
|
|
|
} = this._getInjectionComponents(contract, injectionPoint, fileName, type); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
instrumentation[hash] = { |
|
|
|
|
|
|
|
id: injection.branchId, |
|
|
|
|
|
|
|
locationIdx: injection.locationIdx, |
|
|
|
|
|
|
|
type: type, |
|
|
|
|
|
|
|
contractPath: fileName, |
|
|
|
|
|
|
|
hits: 0 |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
contract.instrumented = `${start}${injectable}${end}`; |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|