Verify integrity of memory initializer using CRC-32

This is almost the standard CRC-32 algorithm, except that we omit the final
XOR with -1 so that we can easily compare the result against zero.
The length of the initializer is included in the data so that we don't have
to worry about leading zeros (after XOR with the init value of -1).

Useful read: http://www.ross.net/crc/download/crc_v3.txt
This commit is contained in:
Martin von Gagern 2015-06-08 22:48:02 +02:00
Родитель c388aeebe7
Коммит 6d3b9ff87a
3 изменённых файлов: 48 добавлений и 4 удалений

20
emcc
Просмотреть файл

@ -1357,14 +1357,28 @@ try:
membytes.pop()
if not membytes:
return '';
membytes = ''.join(map(chr, membytes))
if not memory_init_file:
s = membytes
crcTable = []
for i in range(256):
crc = i
for bit in range(8):
crc = (crc >> 1) ^ ((crc & 1) * 0xedb88320)
crcTable.append(crc)
crc = 0xffffffff
s = list(membytes)
n = len(s)
crc = crcTable[(crc ^ n) & 0xff] ^ (crc >> 8)
crc = crcTable[(crc ^ (n >> 8)) & 0xff] ^ (crc >> 8)
for i in s:
crc = crcTable[(crc ^ i) & 0xff] ^ (crc >> 8)
for i in range(4):
s.append((crc >> (8 * i)) & 0xff)
s = ''.join(map(chr, s))
s = s.replace('\\', '\\\\').replace("'", "\\'")
s = s.replace('\n', '\\n').replace('\r', '\\r')
s = s.decode('latin1').encode('utf8')
return "var memoryInitializer = '%s';" % s
open(memfile, 'wb').write(membytes)
open(memfile, 'wb').write(''.join(map(chr, membytes)))
if DEBUG:
# Copy into temp dir as well, so can be run there too
shared.safe_copy(memfile, os.path.join(shared.get_emscripten_temp_dir(), os.path.basename(memfile)))

Просмотреть файл

@ -7,7 +7,23 @@ if (memoryInitializer && !ENVIRONMENT_IS_PTHREAD) (function(s) {
#else
if (memoryInitializer) (function(s) {
#endif
for (var i = 0; i < s.length; ++i) HEAPU8[STATIC_BASE + i] = s.charCodeAt(i);
var i, n = s.length - 4;
#if ASSERTIONS
var crc, bit, table = new Int32Array(256);
for (i = 0; i < 256; ++i) {
for (crc = i, bit = 0; bit < 8; ++bit)
crc = (crc >>> 1) ^ ((crc & 1) * 0xedb88320);
table[i] = crc >>> 0;
}
crc = -1;
crc = table[(crc ^ n) & 0xff] ^ (crc >>> 8);
crc = table[(crc ^ (n >>> 8)) & 0xff] ^ (crc >>> 8);
for (i = 0; i < s.length; ++i)
crc = table[(crc ^ s.charCodeAt(i)) & 0xff] ^ (crc >>> 8);
assert(crc === 0, "memory initializer checksum");
#endif
for (i = 0; i < n; ++i)
HEAPU8[STATIC_BASE + i] = s.charCodeAt(i);
})(memoryInitializer);
#else
#if MEM_INIT_METHOD == 1

Просмотреть файл

@ -4879,3 +4879,17 @@ int main() {
out, err = Popen([PYTHON, EMCC, 'src.c', '-s', 'EXPORTED_FUNCTIONS=["_main", "_treecount"]', '--minify', '0', '-g4', '-Oz']).communicate()
self.assertContained('hello, world!', run_js('a.out.js'))
def test_meminit_crc(self):
with open('src.c', 'w') as f:
f.write(r'''
#include<stdio.h>
int main() { printf("Mary had a little lamb.\n"); }
''')
out, err = Popen([PYTHON, EMCC, 'src.c', '-O2', '--memory-init-file', '0', '-s', 'MEM_INIT_METHOD=2', '-s', 'ASSERTIONS=1']).communicate()
with open('a.out.js', 'r') as f:
d = f.read()
d = d.replace('Mary had', 'Paul had')
with open('a.out.js', 'w') as f:
f.write(d)
out = run_js('a.out.js', assert_returncode=None, stderr=subprocess.STDOUT)
self.assertContained('Assertion failed: memory initializer checksum', out)