Piping streams into SHA3 without end: false crashes
- Version: 12.4.0
- Platform: Windows 10 x64 and Linux 4.4.0-042stab138.1
- Subsystem: crypto or deps
This code causes a segmentation fault in 12.4.0:
const crypto = require('crypto'); const fs = require('fs'); const myOwnCode = fs.createReadStream(__filename); const copy = fs.createWriteStream(`${__filename}.copy`); const hash = crypto.createHash('sha3-512'); myOwnCode.pipe(hash); myOwnCode.pipe(copy).on('finish', () => { hash.digest(); });
This seems to be caused by pipe calling hash._flush when end is not set to false. This code also causes a segmentation fault:
const crypto = require('crypto'); const hash = crypto.createHash('sha3-512'); hash._flush(() => console.log('Flushed')); hash.digest();
This seems to be at least partially caused by the implementation of _flush:
| Hash.prototype._flush = function _flush(callback) { | |
| this.push(this[kHandle].digest()); | |
| callback(); | |
| }; |
It bypasses the this[kState][kFinalized] safeguard:
| Hash.prototype.digest = function digest(outputEncoding) { | |
| const state = this[kState]; | |
| if (state[kFinalized]) | |
| throw new ERR_CRYPTO_HASH_FINALIZED(); | |
| outputEncoding = outputEncoding || getDefaultEncoding(); | |
| if (normalizeEncoding(outputEncoding) === 'utf16le') | |
| throw new ERR_CRYPTO_HASH_DIGEST_NO_UTF16(); | |
| // Explicit conversion for backward compatibility. | |
| const ret = this[kHandle].digest(`${outputEncoding}`); | |
| state[kFinalized] = true; | |
| return ret; | |
| }; |
Note that this bug only happens when using SHA3, sha256 seems to be working just fine, so there might also be some weirdness in OpenSSL.
cc @mcollina @nodejs/crypto @nodejs/streams