n3 2.11.1 → 2.11.3

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/src/N3Parser.js CHANGED
@@ -54,6 +54,10 @@ export default class N3Parser {
54
54
  // Disable parsing of unsupported versions by default
55
55
  this._parseUnsupportedVersions = !!options.parseUnsupportedVersions;
56
56
  this._version = options.version;
57
+ // Maximum nesting depth of triple terms (default 1024; Infinity disables the limit)
58
+ const maxTripleTermDepth = options.maxTripleTermDepth;
59
+ this._maxTripleTermDepth = maxTripleTermDepth === Infinity ||
60
+ Number.isInteger(maxTripleTermDepth) && maxTripleTermDepth >= 0 ? maxTripleTermDepth : 1024;
57
61
  }
58
62
 
59
63
  // ## Static class methods
@@ -88,6 +92,19 @@ export default class N3Parser {
88
92
  }
89
93
  }
90
94
 
95
+ // ### `_enterTripleTerm` stores the current parsing context when entering a triple term,
96
+ // failing if triple terms nest deeper than the maximum depth
97
+ _enterTripleTerm(type, subject, predicate, token) {
98
+ if (this._tripleTermDepth >= this._maxTripleTermDepth) {
99
+ this._error(`Triple terms nested deeper than ${this._maxTripleTermDepth} level${this._maxTripleTermDepth === 1 ? '' : 's'}`, token);
100
+ return false;
101
+ }
102
+ this._tripleTermDepth++;
103
+ this._saveContext(type, this._graph, subject, predicate, null);
104
+ this._graph = null;
105
+ return true;
106
+ }
107
+
91
108
  // ### `_saveContext` stores the current parsing context
92
109
  // when entering a new scope (list, blank node, formula)
93
110
  _saveContext(type, graph, subject, predicate, object) {
@@ -338,13 +355,9 @@ export default class N3Parser {
338
355
  case '<<(':
339
356
  if (!this._n3Mode)
340
357
  return this._error('Disallowed triple term as subject', token);
341
- this._saveContext('<<(', this._graph, null, null, null);
342
- this._graph = null;
343
- return this._readSubject;
358
+ return this._enterTripleTerm('<<(', null, null, token) && this._readSubject;
344
359
  case '<<':
345
- this._saveContext('<<', this._graph, null, null, null);
346
- this._graph = null;
347
- return this._readSubject;
360
+ return this._enterTripleTerm('<<', null, null, token) && this._readSubject;
348
361
  default:
349
362
  // Read the subject entity
350
363
  if ((this._subject = this._readEntity(token)) === undefined)
@@ -489,13 +502,9 @@ export default class N3Parser {
489
502
  this._graph = this._factory.blankNode());
490
503
  return this._readInFormulaContext;
491
504
  case '<<(':
492
- this._saveContext('<<(', this._graph, this._subject, this._predicate, null);
493
- this._graph = null;
494
- return this._readSubject;
505
+ return this._enterTripleTerm('<<(', this._subject, this._predicate, token) && this._readSubject;
495
506
  case '<<':
496
- this._saveContext('<<', this._graph, this._subject, this._predicate, null);
497
- this._graph = null;
498
- return this._readSubject;
507
+ return this._enterTripleTerm('<<', this._subject, this._predicate, token) && this._readSubject;
499
508
  default:
500
509
  // Read the object entity
501
510
  if ((this._object = this._readEntity(token)) === undefined)
@@ -715,13 +724,9 @@ export default class N3Parser {
715
724
  this._subject = null;
716
725
  return this._readInFormulaContext;
717
726
  case '<<(':
718
- this._saveContext('<<(', this._graph, null, null, null);
719
- this._graph = null;
720
- next = this._readSubject;
721
- break;
722
727
  case '<<':
723
- this._saveContext('<<', this._graph, null, null, null);
724
- this._graph = null;
728
+ if (!this._enterTripleTerm(token.type, null, null, token))
729
+ return;
725
730
  next = this._readSubject;
726
731
  break;
727
732
  default:
@@ -1271,6 +1276,7 @@ export default class N3Parser {
1271
1276
  const quad = this._createQuad(this._subject, this._predicate, this._object,
1272
1277
  this._graph, this._inversePredicate);
1273
1278
  this._restoreContext('<<(', token);
1279
+ this._tripleTermDepth--;
1274
1280
 
1275
1281
  // If we're in a list, continue processing that list
1276
1282
  const stack = this._contextStack, parent = stack.length && stack[stack.length - 1];
@@ -1306,6 +1312,7 @@ export default class N3Parser {
1306
1312
  this._tripleTerm = null;
1307
1313
  const reifier = this._readTripleTerm();
1308
1314
  this._restoreContext('<<', token);
1315
+ this._tripleTermDepth--;
1309
1316
 
1310
1317
  // // If we're in a list, continue processing that list
1311
1318
  const stack = this._contextStack, parent = stack.length && stack[stack.length - 1];
@@ -1651,6 +1658,7 @@ export default class N3Parser {
1651
1658
  this._prefixChanges = null;
1652
1659
  this._quantifiedChanges = null;
1653
1660
  this._emptyFormula = false;
1661
+ this._tripleTermDepth = 0;
1654
1662
 
1655
1663
  let readToken = token => {
1656
1664
  return this._readCallback = this._readCallback(token);
package/src/N3Writer.js CHANGED
@@ -59,6 +59,8 @@ export default class N3Writer {
59
59
  this._lineMode = false;
60
60
  this._graph = DEFAULTGRAPH;
61
61
  this._prefixIRIs = Object.create(null);
62
+ // Escaped prefix IRIs and names for the prefix matcher, computed once per prefix
63
+ this._prefixPatterns = Object.create(null);
62
64
  if (options.baseIRI) {
63
65
  this._baseIri = new BaseIRI(options.baseIRI);
64
66
  if (options.writeBase)
@@ -316,18 +318,19 @@ export default class N3Writer {
316
318
  }
317
319
  // Store and write the prefix
318
320
  this._prefixIRIs[iri] = (prefix += ':');
321
+ this._prefixPatterns[iri] = [escapeRegex(iri), escapeRegex(prefix)];
319
322
  this._write(`@prefix ${prefix} <${iri}>.\n`);
320
323
  }
321
324
  // Recreate the prefix matcher
322
325
  if (hasPrefixes) {
323
326
  this._hasPrefixes = true;
324
327
  let IRIlist = '', prefixList = '';
325
- for (const prefixIRI in this._prefixIRIs) {
326
- IRIlist += IRIlist ? `|${prefixIRI}` : prefixIRI;
327
- prefixList += (prefixList ? '|' : '') + this._prefixIRIs[prefixIRI];
328
+ for (const prefixIRI in this._prefixPatterns) {
329
+ const [IRIpattern, prefixPattern] = this._prefixPatterns[prefixIRI];
330
+ IRIlist += IRIlist ? `|${IRIpattern}` : IRIpattern;
331
+ prefixList += prefixList ? `|${prefixPattern}` : prefixPattern;
328
332
  }
329
- IRIlist = escapeRegex(IRIlist, /[\]\/\(\)\*\+\?\.\\\$]/g, '\\$&');
330
- this._prefixRegex = new RegExp(`^(?:${prefixList})[^\/]*$|` +
333
+ this._prefixRegex = new RegExp(`^(?:${prefixList})[^/]*$|` +
331
334
  `^(${IRIlist})([_a-zA-Z0-9](?:\\.?[\\-_a-zA-Z0-9])*)$`);
332
335
  }
333
336
  // End a prefix block with a newline
package/src/Util.js CHANGED
@@ -1,3 +1,3 @@
1
1
  export function escapeRegex(regex) {
2
- return regex.replace(/[\]\/\(\)\*\+\?\.\\\$]/g, '\\$&');
2
+ return regex.replace(/[.*+?^${}()|[\]\\/-]/g, '\\$&');
3
3
  }