@theqrl/hypc 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/formatters.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.formatFatalError = void 0;
3
+ exports.formatFatalError = formatFatalError;
4
4
  function formatFatalError(message) {
5
5
  return JSON.stringify({
6
6
  errors: [
@@ -8,10 +8,9 @@ function formatFatalError(message) {
8
8
  type: 'JSONError',
9
9
  component: 'hypcjs',
10
10
  severity: 'error',
11
- message: message,
11
+ message,
12
12
  formattedMessage: 'Error: ' + message
13
13
  }
14
14
  ]
15
15
  });
16
16
  }
17
- exports.formatFatalError = formatFatalError;
package/hypc.js CHANGED
@@ -16,13 +16,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
16
16
  }) : function(o, v) {
17
17
  o["default"] = v;
18
18
  });
19
- var __importStar = (this && this.__importStar) || function (mod) {
20
- if (mod && mod.__esModule) return mod;
21
- var result = {};
22
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
23
- __setModuleDefault(result, mod);
24
- return result;
25
- };
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
26
36
  var __importDefault = (this && this.__importDefault) || function (mod) {
27
37
  return (mod && mod.__esModule) ? mod : { "default": mod };
28
38
  };
@@ -41,16 +51,15 @@ const originalUncaughtExceptionListeners = process.listeners('uncaughtException'
41
51
  process.removeAllListeners('uncaughtException');
42
52
  const program = new commander.Command();
43
53
  const commanderParseInt = function (value) {
44
- const parsedValue = parseInt(value, 10);
45
- if (isNaN(parsedValue)) {
54
+ if (!/^\d+$/.test(value)) {
46
55
  throw new commander.InvalidArgumentError('Not a valid integer.');
47
56
  }
48
- return parsedValue;
57
+ return parseInt(value, 10);
49
58
  };
50
59
  program.name('hypcjs');
51
- program.version(index_1.default.version());
60
+ program.version(index_1.default.version(), '-V, --version', 'Show version and exit.');
52
61
  program
53
- .option('--version', 'Show version and exit.')
62
+ .argument('[files...]', 'Source files to compile.')
54
63
  .option('--optimize', 'Enable bytecode optimizer.', false)
55
64
  .option('--optimize-runs <optimize-runs>', 'The number of runs specifies roughly how often each opcode of the deployed code will be executed across the lifetime of the contract. ' +
56
65
  'Lower values will optimize more for initial deployment cost, higher values will optimize more for high-frequency usage.', commanderParseInt)
@@ -73,11 +82,43 @@ function abort(msg) {
73
82
  console.error(msg || 'Error occurred');
74
83
  process.exit(1);
75
84
  }
85
+ function realPathIfExists(filePath) {
86
+ try {
87
+ return fs.realpathSync(filePath);
88
+ }
89
+ catch (e) {
90
+ return path.resolve(filePath);
91
+ }
92
+ }
93
+ // As in hypc, imports may only be read from the base path (the working directory by default),
94
+ // the include paths and the directories of the files given on the command line. Symlinks are
95
+ // resolved before the check, so a link cannot point outside these directories.
96
+ // Without a base path the working directory is not allowed when it is the root of the filesystem
97
+ // (or of a drive on Windows), since that would make every readable file importable.
98
+ function defaultAllowedDirectories() {
99
+ if (options.basePath) {
100
+ return [options.basePath];
101
+ }
102
+ const workingDirectory = realPathIfExists('.');
103
+ return path.parse(workingDirectory).root === workingDirectory ? [] : [workingDirectory];
104
+ }
105
+ const allowedDirectories = defaultAllowedDirectories()
106
+ .concat(options.includePath || [], files.map((file) => path.dirname(file)))
107
+ .map(realPathIfExists);
108
+ function isInsideAllowedDirectory(filePath) {
109
+ return allowedDirectories.some((directory) => {
110
+ const relativePath = path.relative(directory, filePath);
111
+ return relativePath === '' || (relativePath.split(path.sep)[0] !== '..' && !path.isAbsolute(relativePath));
112
+ });
113
+ }
76
114
  function readFileCallback(sourcePath) {
77
115
  const prefixes = [options.basePath ? options.basePath : ''].concat(options.includePath ? options.includePath : []);
78
116
  for (const prefix of prefixes) {
79
117
  const prefixedSourcePath = (prefix ? prefix + '/' : '') + sourcePath;
80
118
  if (fs.existsSync(prefixedSourcePath)) {
119
+ if (!isInsideAllowedDirectory(fs.realpathSync(prefixedSourcePath))) {
120
+ return { error: 'File outside of allowed directories.' };
121
+ }
81
122
  try {
82
123
  return { contents: fs.readFileSync(prefixedSourcePath).toString('utf8') };
83
124
  }
@@ -117,10 +158,25 @@ function makeSourcePathRelativeIfPossible(sourcePath) {
117
158
  return withUnixPathSeparators(absoluteSourcePath);
118
159
  }
119
160
  function toFormattedJson(input) {
120
- return JSON.stringify(input, null, program.prettyJson ? 4 : 0);
161
+ return JSON.stringify(input, null, options.prettyJson ? 4 : 0);
121
162
  }
163
+ // Input that is not valid JSON is returned as it is, so that the compiler reports it.
122
164
  function reformatJsonIfRequested(inputJson) {
123
- return (program.prettyJson ? toFormattedJson(JSON.parse(inputJson)) : inputJson);
165
+ if (!options.prettyJson) {
166
+ return inputJson;
167
+ }
168
+ try {
169
+ return toFormattedJson(JSON.parse(inputJson));
170
+ }
171
+ catch (e) {
172
+ return inputJson;
173
+ }
174
+ }
175
+ // Diagnostics go to stderr, so that stdout carries only the compiler output.
176
+ function verbose(message) {
177
+ if (options.verbose) {
178
+ console.error(message);
179
+ }
124
180
  }
125
181
  let callbacks;
126
182
  if (options.basePath || !options.standardJson) {
@@ -128,20 +184,16 @@ if (options.basePath || !options.standardJson) {
128
184
  }
129
185
  if (options.standardJson) {
130
186
  const input = fs.readFileSync(process.stdin.fd).toString('utf8');
131
- if (program.verbose) {
132
- console.log('>>> Compiling:\n' + reformatJsonIfRequested(input) + '\n');
133
- }
187
+ verbose('>>> Compiling:\n' + reformatJsonIfRequested(input) + '\n');
134
188
  let output = reformatJsonIfRequested(index_1.default.compile(input, callbacks));
135
189
  try {
136
190
  if (smtsolver_1.default.availableSolvers.length === 0) {
137
- console.log('>>> Cannot retry compilation with SMT because there are no SMT solvers available.');
191
+ verbose('>>> Cannot retry compilation with SMT because there are no SMT solvers available.');
138
192
  }
139
193
  else {
140
194
  const inputJSON = smtchecker_1.default.handleSMTQueries(JSON.parse(input), JSON.parse(output), smtsolver_1.default.smtSolver, smtsolver_1.default.availableSolvers[0]);
141
195
  if (inputJSON) {
142
- if (program.verbose) {
143
- console.log('>>> Retrying compilation with SMT:\n' + toFormattedJson(inputJSON) + '\n');
144
- }
196
+ verbose('>>> Retrying compilation with SMT:\n' + toFormattedJson(inputJSON) + '\n');
145
197
  output = reformatJsonIfRequested(index_1.default.compile(JSON.stringify(inputJSON), callbacks));
146
198
  }
147
199
  }
@@ -160,9 +212,7 @@ if (options.standardJson) {
160
212
  outputJSON.errors.push(addError);
161
213
  output = toFormattedJson(outputJSON);
162
214
  }
163
- if (program.verbose) {
164
- console.log('>>> Compilation result:');
165
- }
215
+ verbose('>>> Compilation result:');
166
216
  console.log(output);
167
217
  process.exit(0);
168
218
  }
@@ -207,11 +257,9 @@ const cliInput = {
207
257
  }
208
258
  }
209
259
  },
210
- sources: sources
260
+ sources
211
261
  };
212
- if (program.verbose) {
213
- console.log('>>> Compiling:\n' + toFormattedJson(cliInput) + '\n');
214
- }
262
+ verbose('>>> Compiling:\n' + toFormattedJson(cliInput) + '\n');
215
263
  const output = JSON.parse(index_1.default.compile(JSON.stringify(cliInput), callbacks));
216
264
  let hasError = false;
217
265
  if (!output) {
@@ -232,16 +280,24 @@ else if (output.errors) {
232
280
  fs.mkdirSync(destination, { recursive: true });
233
281
  function writeFile(file, content) {
234
282
  file = path.join(destination, file);
235
- fs.writeFile(file, content, function (err) {
236
- if (err) {
237
- console.error('Failed to write ' + file + ': ' + err);
238
- }
239
- });
283
+ try {
284
+ fs.writeFileSync(file, content);
285
+ }
286
+ catch (err) {
287
+ console.error('Failed to write ' + file + ': ' + err);
288
+ }
240
289
  }
290
+ // Output names replace ':', '.', '/' and '\' with '_', so different contracts can map to one name.
291
+ const outputNames = new Map();
241
292
  for (const fileName in output.contracts) {
242
293
  for (const contractName in output.contracts[fileName]) {
243
294
  let contractFileName = fileName + ':' + contractName;
244
295
  contractFileName = contractFileName.replace(/[:./\\]/g, '_');
296
+ const previous = outputNames.get(contractFileName);
297
+ if (previous) {
298
+ console.error(`Warning: ${previous} and ${fileName}:${contractName} both write ${contractFileName}; the output of ${fileName}:${contractName} replaces the other.`);
299
+ }
300
+ outputNames.set(contractFileName, `${fileName}:${contractName}`);
245
301
  if (options.bin) {
246
302
  writeFile(contractFileName + '.bin', output.contracts[fileName][contractName].qrvm.bytecode.object);
247
303
  }