aboutsummaryrefslogtreecommitdiff
path: root/dev
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2023-12-19 00:33:38 -0500
committerGitHub <noreply@github.com>2023-12-19 05:33:38 +0000
commit1ced9aafc00c10992bab8bd3f1b6b1397f05b7b9 (patch)
tree305bb2b3bfc7fc3b051ee1cd3d1c35f442af0de4 /dev
parent5f96276fda93dcad39f2165fd3c8d890aa5f9be5 (diff)
Make JSON.parse usage safer (#373)
* Make JSON.parse usage safer * Fix any type * Add readResponseJson * Use readResponseJson * Additional updates * Rename files * Add types
Diffstat (limited to 'dev')
-rw-r--r--dev/bin/schema-validate.js5
-rw-r--r--dev/build-libs.js7
-rw-r--r--dev/dictionary-validate.js8
-rw-r--r--dev/json.js18
-rw-r--r--dev/manifest-util.js5
-rw-r--r--dev/schema-validate.js6
-rw-r--r--dev/util.js5
7 files changed, 42 insertions, 12 deletions
diff --git a/dev/bin/schema-validate.js b/dev/bin/schema-validate.js
index 206f26ca..bbd5ad5f 100644
--- a/dev/bin/schema-validate.js
+++ b/dev/bin/schema-validate.js
@@ -18,6 +18,7 @@
import fs from 'fs';
import {performance} from 'perf_hooks';
+import {parseJson} from '../../ext/js/core/json.js';
import {createJsonSchema} from '../schema-validate.js';
/** */
@@ -39,14 +40,14 @@ function main() {
}
const schemaSource = fs.readFileSync(args[0], {encoding: 'utf8'});
- const schema = JSON.parse(schemaSource);
+ const schema = parseJson(schemaSource);
for (const dataFileName of args.slice(1)) {
const start = performance.now();
try {
console.log(`Validating ${dataFileName}...`);
const dataSource = fs.readFileSync(dataFileName, {encoding: 'utf8'});
- const data = JSON.parse(dataSource);
+ const data = parseJson(dataSource);
createJsonSchema(mode, schema).validate(data);
const end = performance.now();
console.log(`No issues detected (${((end - start) / 1000).toFixed(2)}s)`);
diff --git a/dev/build-libs.js b/dev/build-libs.js
index a992f20a..10720010 100644
--- a/dev/build-libs.js
+++ b/dev/build-libs.js
@@ -22,6 +22,7 @@ import esbuild from 'esbuild';
import fs from 'fs';
import path from 'path';
import {fileURLToPath} from 'url';
+import {parseJson} from './json.js';
const dirname = path.dirname(fileURLToPath(import.meta.url));
const extDir = path.join(dirname, '..', 'ext');
@@ -61,7 +62,11 @@ export async function buildLibs() {
const schemaDir = path.join(extDir, 'data/schemas/');
const schemaFileNames = fs.readdirSync(schemaDir);
- const schemas = schemaFileNames.map((schemaFileName) => JSON.parse(fs.readFileSync(path.join(schemaDir, schemaFileName), {encoding: 'utf8'})));
+ const schemas = schemaFileNames.map((schemaFileName) => {
+ /** @type {import('ajv').AnySchema} */
+ const result = parseJson(fs.readFileSync(path.join(schemaDir, schemaFileName), {encoding: 'utf8'}));
+ return result;
+ });
const ajv = new Ajv({
schemas,
code: {source: true, esm: true},
diff --git a/dev/dictionary-validate.js b/dev/dictionary-validate.js
index 7842c65e..efc2eb8c 100644
--- a/dev/dictionary-validate.js
+++ b/dev/dictionary-validate.js
@@ -21,6 +21,7 @@ import JSZip from 'jszip';
import path from 'path';
import {performance} from 'perf_hooks';
import {fileURLToPath} from 'url';
+import {parseJson} from './json.js';
import {createJsonSchema} from './schema-validate.js';
const dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -32,7 +33,7 @@ const dirname = path.dirname(fileURLToPath(import.meta.url));
function readSchema(relativeFileName) {
const fileName = path.join(dirname, relativeFileName);
const source = fs.readFileSync(fileName, {encoding: 'utf8'});
- return JSON.parse(source);
+ return parseJson(source);
}
/**
@@ -57,7 +58,7 @@ async function validateDictionaryBanks(mode, zip, fileNameFormat, schema) {
const file = zip.files[fileName];
if (!file) { break; }
- const data = JSON.parse(await file.async('string'));
+ const data = parseJson(await file.async('string'));
try {
jsonSchema.validate(data);
} catch (e) {
@@ -83,7 +84,8 @@ export async function validateDictionary(mode, archive, schemas) {
throw new Error('No dictionary index found in archive');
}
- const index = JSON.parse(await indexFile.async('string'));
+ /** @type {import('dictionary-data').Index} */
+ const index = parseJson(await indexFile.async('string'));
const version = index.format || index.version;
try {
diff --git a/dev/json.js b/dev/json.js
new file mode 100644
index 00000000..a76edfcd
--- /dev/null
+++ b/dev/json.js
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2023 Yomitan Authors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+export {parseJson} from '../ext/js/core/json.js';
diff --git a/dev/manifest-util.js b/dev/manifest-util.js
index 638706d8..ac9b58db 100644
--- a/dev/manifest-util.js
+++ b/dev/manifest-util.js
@@ -20,6 +20,7 @@ import childProcess from 'child_process';
import fs from 'fs';
import {fileURLToPath} from 'node:url';
import path from 'path';
+import {parseJson} from './json.js';
const dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -29,14 +30,14 @@ const dirname = path.dirname(fileURLToPath(import.meta.url));
* @returns {T}
*/
function clone(value) {
- return JSON.parse(JSON.stringify(value));
+ return parseJson(JSON.stringify(value));
}
export class ManifestUtil {
constructor() {
const fileName = path.join(dirname, 'data', 'manifest-variants.json');
- const {manifest, variants, defaultVariant} = /** @type {import('dev/manifest').ManifestConfig} */ (JSON.parse(fs.readFileSync(fileName, {encoding: 'utf8'})));
+ const {manifest, variants, defaultVariant} = /** @type {import('dev/manifest').ManifestConfig} */ (parseJson(fs.readFileSync(fileName, {encoding: 'utf8'})));
/** @type {import('dev/manifest').Manifest} */
this._manifest = manifest;
/** @type {import('dev/manifest').ManifestVariant[]} */
diff --git a/dev/schema-validate.js b/dev/schema-validate.js
index 81953f49..57faf96c 100644
--- a/dev/schema-validate.js
+++ b/dev/schema-validate.js
@@ -20,6 +20,7 @@ import Ajv from 'ajv';
import {readFileSync} from 'fs';
import {JsonSchema} from '../ext/js/data/json-schema.js';
import {DataError} from './data-error.js';
+import {parseJson} from './json.js';
class JsonSchemaAjv {
/**
@@ -32,7 +33,8 @@ class JsonSchemaAjv {
allowUnionTypes: true
});
const metaSchemaPath = require.resolve('ajv/dist/refs/json-schema-draft-07.json');
- const metaSchema = JSON.parse(readFileSync(metaSchemaPath, {encoding: 'utf8'}));
+ /** @type {import('ajv').AnySchemaObject} */
+ const metaSchema = parseJson(readFileSync(metaSchemaPath, {encoding: 'utf8'}));
ajv.addMetaSchema(metaSchema);
/** @type {import('ajv').ValidateFunction} */
this._validate = ajv.compile(/** @type {import('ajv').Schema} */ (schema));
@@ -46,7 +48,7 @@ class JsonSchemaAjv {
if (this._validate(data)) { return; }
const {errors} = this._validate;
const error = new DataError('Schema validation failed');
- error.data = JSON.parse(JSON.stringify(errors));
+ error.data = parseJson(JSON.stringify(errors));
throw error;
}
}
diff --git a/dev/util.js b/dev/util.js
index f45966c4..6a7fa8f5 100644
--- a/dev/util.js
+++ b/dev/util.js
@@ -19,6 +19,7 @@
import fs from 'fs';
import JSZip from 'jszip';
import path from 'path';
+import {parseJson} from './json.js';
/**
* @param {string[]} args
@@ -112,9 +113,9 @@ export function createDictionaryArchive(dictionaryDirectory, dictionaryName) {
for (const fileName of fileNames) {
if (/\.json$/.test(fileName)) {
const content = fs.readFileSync(path.join(dictionaryDirectory, fileName), {encoding: 'utf8'});
- const json = JSON.parse(content);
+ const json = parseJson(content);
if (fileName === 'index.json' && typeof dictionaryName === 'string') {
- json.title = dictionaryName;
+ /** @type {import('dictionary-data').Index} */ (json).title = dictionaryName;
}
archive.file(fileName, JSON.stringify(json, null, 0));