packager: TransformCache: use sha1 instead of murmurhash

Reviewed By: davidaurelio

Differential Revision: D4809941

fbshipit-source-id: 33b6c56b4c48eca88d8c1922f52ed29a728d1173
This commit is contained in:
Jean Lauliac 2017-04-03 05:49:40 -07:00 committed by Facebook Github Bot
parent 83e38fe2ca
commit a6bcbd61e6
3 changed files with 22 additions and 45 deletions

View File

@ -11,19 +11,13 @@
'use strict'; 'use strict';
const crypto = require('crypto');
const debugRead = require('debug')('RNP:TransformCache:Read'); const debugRead = require('debug')('RNP:TransformCache:Read');
const fs = require('fs'); const fs = require('fs');
/**
* We get the package "for free" with "write-file-atomic". MurmurHash3 is a
* faster hash, but non-cryptographic and insecure, that seems reasonnable for
* this particular use case.
*/
const imurmurhash = require('imurmurhash');
const mkdirp = require('mkdirp'); const mkdirp = require('mkdirp');
const path = require('path'); const path = require('path');
const rimraf = require('rimraf'); const rimraf = require('rimraf');
const terminal = require('../lib/terminal'); const terminal = require('../lib/terminal');
const toFixedHex = require('./toFixedHex');
const writeFileAtomicSync = require('write-file-atomic').sync; const writeFileAtomicSync = require('write-file-atomic').sync;
const CACHE_NAME = 'react-native-packager-cache'; const CACHE_NAME = 'react-native-packager-cache';
@ -47,9 +41,9 @@ const getCacheDirPath = (function() {
if (dirPath == null) { if (dirPath == null) {
dirPath = path.join( dirPath = path.join(
require('os').tmpdir(), require('os').tmpdir(),
CACHE_NAME + '-' + imurmurhash(__dirname).result().toString(16), CACHE_NAME + '-' + crypto.createHash('sha1')
.update(__dirname).digest('base64'),
); );
require('debug')('RNP:TransformCache:Dir')( require('debug')('RNP:TransformCache:Dir')(
`transform cache directory: ${dirPath}` `transform cache directory: ${dirPath}`
); );
@ -65,11 +59,14 @@ function hashSourceCode(props: {
transformOptions: TransformOptions, transformOptions: TransformOptions,
transformOptionsKey: string, transformOptionsKey: string,
}): string { }): string {
return imurmurhash(props.getTransformCacheKey( return crypto.createHash('sha1')
props.sourceCode, .update(props.getTransformCacheKey(
props.filePath, props.sourceCode,
props.transformOptions, props.filePath,
)).hash(props.sourceCode).result(); props.transformOptions,
))
.update(props.sourceCode)
.digest('hex');
} }
/** /**
@ -81,10 +78,10 @@ function getCacheFilePaths(props: {
filePath: string, filePath: string,
transformOptionsKey: string, transformOptionsKey: string,
}): CacheFilePaths { }): CacheFilePaths {
const hasher = imurmurhash() const hasher = crypto.createHash('sha1')
.hash(props.filePath) .update(props.filePath)
.hash(props.transformOptionsKey); .update(props.transformOptionsKey);
const hash = toFixedHex(8, hasher.result()); const hash = hasher.digest('hex');
const prefix = hash.substr(0, 2); const prefix = hash.substr(0, 2);
const fileName = `${hash.substr(2)}${path.basename(props.filePath)}`; const fileName = `${hash.substr(2)}${path.basename(props.filePath)}`;
const base = path.join(getCacheDirPath(), prefix, fileName); const base = path.join(getCacheDirPath(), prefix, fileName);
@ -145,7 +142,7 @@ function writeSync(props: {
unlinkIfExistsSync(cacheFilePath.metadata); unlinkIfExistsSync(cacheFilePath.metadata);
writeFileAtomicSync(cacheFilePath.transformedCode, result.code); writeFileAtomicSync(cacheFilePath.transformedCode, result.code);
writeFileAtomicSync(cacheFilePath.metadata, JSON.stringify([ writeFileAtomicSync(cacheFilePath.metadata, JSON.stringify([
imurmurhash(result.code).result(), crypto.createHash('sha1').update(result.code).digest('hex'),
hashSourceCode(props), hashSourceCode(props),
result.dependencies, result.dependencies,
result.dependencyOffsets, result.dependencyOffsets,
@ -243,8 +240,8 @@ const GARBAGE_COLLECTOR = new (class GarbageCollector {
function readMetadataFileSync( function readMetadataFileSync(
metadataFilePath: string, metadataFilePath: string,
): ?{ ): ?{
cachedResultHash: number, cachedResultHash: string,
cachedSourceHash: number, cachedSourceHash: string,
dependencies: Array<string>, dependencies: Array<string>,
dependencyOffsets: Array<number>, dependencyOffsets: Array<number>,
sourceMap: ?SourceMap, sourceMap: ?SourceMap,
@ -270,8 +267,8 @@ function readMetadataFileSync(
sourceMap, sourceMap,
] = metadata; ] = metadata;
if ( if (
typeof cachedResultHash !== 'number' || typeof cachedResultHash !== 'string' ||
typeof cachedSourceHash !== 'number' || typeof cachedSourceHash !== 'string' ||
!( !(
Array.isArray(dependencies) && Array.isArray(dependencies) &&
dependencies.every(dep => typeof dep === 'string') dependencies.every(dep => typeof dep === 'string')
@ -329,7 +326,8 @@ function readSync(props: ReadTransformProps): ?CachedResult {
return null; return null;
} }
transformedCode = fs.readFileSync(cacheFilePaths.transformedCode, 'utf8'); transformedCode = fs.readFileSync(cacheFilePaths.transformedCode, 'utf8');
if (metadata.cachedResultHash !== imurmurhash(transformedCode).result()) { const codeHash = crypto.createHash('sha1').update(transformedCode).digest('hex');
if (metadata.cachedResultHash !== codeHash) {
return null; return null;
} }
} catch (error) { } catch (error) {

View File

@ -13,7 +13,6 @@ jest
.dontMock('imurmurhash') .dontMock('imurmurhash')
.dontMock('json-stable-stringify') .dontMock('json-stable-stringify')
.dontMock('../TransformCache') .dontMock('../TransformCache')
.dontMock('../toFixedHex')
.dontMock('left-pad') .dontMock('left-pad')
.dontMock('lodash/throttle') .dontMock('lodash/throttle')
.dontMock('crypto'); .dontMock('crypto');

View File

@ -1,20 +0,0 @@
/**
* Copyright (c) 2016-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
*/
'use strict';
const leftPad = require('left-pad');
function toFixedHex(length: number, number: number): string {
return leftPad(number.toString(16), length, '0');
}
module.exports = toFixedHex;