@openforis/arena-core 2.17.0 → 2.18.0

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.
@@ -19,7 +19,9 @@ export declare const SystemErrorKeys: {
19
19
  readonly multipleNodesFoundForNodeDef: 'expression.multipleNodesFoundForNodeDef';
20
20
  readonly nodeNotFoundForNodeDef: 'expression.nodeNotFoundForNodeDef';
21
21
  readonly notSupported: 'expression.notSupported';
22
+ readonly regularExpressionInputTooLong: 'expression.regularExpressionInputTooLong';
22
23
  readonly unaryOperatorNotSupported: 'expression.unaryOperatorNotSupported';
24
+ readonly unsafeRegularExpression: 'expression.unsafeRegularExpression';
23
25
  readonly undefinedFunction: 'expression.undefinedFunction';
24
26
  readonly unsupportedFunctionType: 'expression.unsupportedFunctionType';
25
27
  };
@@ -22,7 +22,9 @@ exports.SystemErrorKeys = {
22
22
  multipleNodesFoundForNodeDef: 'expression.multipleNodesFoundForNodeDef',
23
23
  nodeNotFoundForNodeDef: 'expression.nodeNotFoundForNodeDef',
24
24
  notSupported: 'expression.notSupported',
25
+ regularExpressionInputTooLong: 'expression.regularExpressionInputTooLong',
25
26
  unaryOperatorNotSupported: 'expression.unaryOperatorNotSupported',
27
+ unsafeRegularExpression: 'expression.unsafeRegularExpression',
26
28
  undefinedFunction: 'expression.undefinedFunction',
27
29
  unsupportedFunctionType: 'expression.unsupportedFunctionType',
28
30
  },
@@ -1 +1 @@
1
- {"version":3,"file":"systemErrorKeys.js","sourceRoot":"","sources":["../../src/error/systemErrorKeys.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACU,QAAA,eAAe,GAAG;IAC7B,UAAU,EAAE;QACV,sBAAsB,EAAE,mCAAmC;QAC3D,2BAA2B,EAAE,wCAAwC;QACrE,0BAA0B,EAAE,uCAAuC;QACnE,2BAA2B,EAAE,wCAAwC;QACrE,kBAAkB,EAAE,+BAA+B;QACnD,iCAAiC,EAAE,8CAA8C;QACjF,iBAAiB,EAAE,8BAA8B;QACjD,wBAAwB,EAAE,qCAAqC;QAC/D,mBAAmB,EAAE,gCAAgC;QACrD,sCAAsC,EAAE,mDAAmD;QAC3F,wBAAwB,EAAE,qCAAqC;QAC/D,mBAAmB,EAAE,gCAAgC;QACrD,yBAAyB,EAAE,sCAAsC;QACjE,4BAA4B,EAAE,yCAAyC;QACvE,sBAAsB,EAAE,mCAAmC;QAC3D,YAAY,EAAE,yBAAyB;QACvC,yBAAyB,EAAE,sCAAsC;QACjE,iBAAiB,EAAE,8BAA8B;QACjD,uBAAuB,EAAE,oCAAoC;KAC9D;IACD,GAAG,EAAE;QACH,cAAc,EAAE,oBAAoB;QACpC,WAAW,EAAE,iBAAiB;QAC9B,eAAe,EAAE,qBAAqB;KACvC;IACD,GAAG,EAAE;QACH,qBAAqB,EAAE,0BAA0B;KAClD;IACD,OAAO,EAAE;QACP,2BAA2B,EAAE,qCAAqC;QAClE,cAAc,EAAE,wBAAwB;KACzC;IACD,MAAM,EAAE;QACN,qBAAqB,EAAE,+CAA+C;QACtE,sBAAsB,EAAE,+BAA+B;QACvD,kBAAkB,EAAE,uCAAuC;QAC3D,YAAY,EAAE,qBAAqB;QACnC,wBAAwB,EAAE,iCAAiC;QAC3D,oCAAoC,EAAE,6CAA6C;QACnF,gCAAgC,EAAE,yCAAyC;KAC5E;IACD,MAAM,EAAE;QACN,aAAa,EAAE,sBAAsB;QACrC,mBAAmB,EAAE,4BAA4B;QACjD,mBAAmB,EAAE,4BAA4B;QACjD,eAAe,EAAE,wBAAwB;KAC1C;CACO,CAAA","sourcesContent":["/**\n * Keys of the errors thrown by arena-core as SystemError (translatable, see SystemError.key).\n */\nexport const SystemErrorKeys = {\n expression: {\n areaOfInterestNotFound: 'expression.areaOfInterestNotFound',\n booleanOperatorNotSupported: 'expression.booleanOperatorNotSupported',\n functionHasTooFewArguments: 'expression.functionHasTooFewArguments',\n functionHasTooManyArguments: 'expression.functionHasTooManyArguments',\n identifierNotFound: 'expression.identifierNotFound',\n invalidAttributeValuePropertyName: 'expression.invalidAttributeValuePropertyName',\n invalidCalleeType: 'expression.invalidCalleeType',\n invalidCategoryExtraProp: 'expression.invalidCategoryExtraProp',\n invalidCategoryName: 'expression.invalidCategoryName',\n invalidTaxonVernacularNameLanguageCode: 'expression.invalidTaxonVernacularNameLanguageCode',\n invalidTaxonomyExtraProp: 'expression.invalidTaxonomyExtraProp',\n invalidTaxonomyName: 'expression.invalidTaxonomyName',\n missingFunctionParameters: 'expression.missingFunctionParameters',\n multipleNodesFoundForNodeDef: 'expression.multipleNodesFoundForNodeDef',\n nodeNotFoundForNodeDef: 'expression.nodeNotFoundForNodeDef',\n notSupported: 'expression.notSupported',\n unaryOperatorNotSupported: 'expression.unaryOperatorNotSupported',\n undefinedFunction: 'expression.undefinedFunction',\n unsupportedFunctionType: 'expression.unsupportedFunctionType',\n },\n geo: {\n pointNotFilled: 'geo.pointNotFilled',\n srsNotFound: 'geo.srsNotFound',\n transformFailed: 'geo.transformFailed',\n },\n job: {\n canceledOrErrorsFound: 'jobCanceledOrErrorsFound',\n },\n nodeDef: {\n hierarchyCircularDependency: 'nodeDef.hierarchyCircularDependency',\n parentNotFound: 'nodeDef.parentNotFound',\n },\n record: {\n dependencyOnRootFound: 'record.nodes.dependents.dependencyOnRootFound',\n enumeratorNodeNotFound: 'record.enumeratorNodeNotFound',\n multipleNodesFound: 'systemError.record.multipleNodesFound',\n nodeNotFound: 'record.nodeNotFound',\n nodesIndexNotInitialized: 'record.nodesIndexNotInitialized',\n updateSelfAndDependentsDefaultValues: 'record.updateSelfAndDependentsDefaultValues',\n updateSelfAndDependentsFileNames: 'record.updateSelfAndDependentsFileNames',\n },\n survey: {\n emptyNodeDefs: 'survey.emptyNodeDefs',\n nodeDefNameNotFound: 'survey.nodeDefNameNotFound',\n nodeDefUuidNotFound: 'survey.nodeDefUuidNotFound',\n rootDefNotFound: 'survey.rootDefNotFound',\n },\n} as const\n"]}
1
+ {"version":3,"file":"systemErrorKeys.js","sourceRoot":"","sources":["../../src/error/systemErrorKeys.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACU,QAAA,eAAe,GAAG;IAC7B,UAAU,EAAE;QACV,sBAAsB,EAAE,mCAAmC;QAC3D,2BAA2B,EAAE,wCAAwC;QACrE,0BAA0B,EAAE,uCAAuC;QACnE,2BAA2B,EAAE,wCAAwC;QACrE,kBAAkB,EAAE,+BAA+B;QACnD,iCAAiC,EAAE,8CAA8C;QACjF,iBAAiB,EAAE,8BAA8B;QACjD,wBAAwB,EAAE,qCAAqC;QAC/D,mBAAmB,EAAE,gCAAgC;QACrD,sCAAsC,EAAE,mDAAmD;QAC3F,wBAAwB,EAAE,qCAAqC;QAC/D,mBAAmB,EAAE,gCAAgC;QACrD,yBAAyB,EAAE,sCAAsC;QACjE,4BAA4B,EAAE,yCAAyC;QACvE,sBAAsB,EAAE,mCAAmC;QAC3D,YAAY,EAAE,yBAAyB;QACvC,6BAA6B,EAAE,0CAA0C;QACzE,yBAAyB,EAAE,sCAAsC;QACjE,uBAAuB,EAAE,oCAAoC;QAC7D,iBAAiB,EAAE,8BAA8B;QACjD,uBAAuB,EAAE,oCAAoC;KAC9D;IACD,GAAG,EAAE;QACH,cAAc,EAAE,oBAAoB;QACpC,WAAW,EAAE,iBAAiB;QAC9B,eAAe,EAAE,qBAAqB;KACvC;IACD,GAAG,EAAE;QACH,qBAAqB,EAAE,0BAA0B;KAClD;IACD,OAAO,EAAE;QACP,2BAA2B,EAAE,qCAAqC;QAClE,cAAc,EAAE,wBAAwB;KACzC;IACD,MAAM,EAAE;QACN,qBAAqB,EAAE,+CAA+C;QACtE,sBAAsB,EAAE,+BAA+B;QACvD,kBAAkB,EAAE,uCAAuC;QAC3D,YAAY,EAAE,qBAAqB;QACnC,wBAAwB,EAAE,iCAAiC;QAC3D,oCAAoC,EAAE,6CAA6C;QACnF,gCAAgC,EAAE,yCAAyC;KAC5E;IACD,MAAM,EAAE;QACN,aAAa,EAAE,sBAAsB;QACrC,mBAAmB,EAAE,4BAA4B;QACjD,mBAAmB,EAAE,4BAA4B;QACjD,eAAe,EAAE,wBAAwB;KAC1C;CACO,CAAA","sourcesContent":["/**\n * Keys of the errors thrown by arena-core as SystemError (translatable, see SystemError.key).\n */\nexport const SystemErrorKeys = {\n expression: {\n areaOfInterestNotFound: 'expression.areaOfInterestNotFound',\n booleanOperatorNotSupported: 'expression.booleanOperatorNotSupported',\n functionHasTooFewArguments: 'expression.functionHasTooFewArguments',\n functionHasTooManyArguments: 'expression.functionHasTooManyArguments',\n identifierNotFound: 'expression.identifierNotFound',\n invalidAttributeValuePropertyName: 'expression.invalidAttributeValuePropertyName',\n invalidCalleeType: 'expression.invalidCalleeType',\n invalidCategoryExtraProp: 'expression.invalidCategoryExtraProp',\n invalidCategoryName: 'expression.invalidCategoryName',\n invalidTaxonVernacularNameLanguageCode: 'expression.invalidTaxonVernacularNameLanguageCode',\n invalidTaxonomyExtraProp: 'expression.invalidTaxonomyExtraProp',\n invalidTaxonomyName: 'expression.invalidTaxonomyName',\n missingFunctionParameters: 'expression.missingFunctionParameters',\n multipleNodesFoundForNodeDef: 'expression.multipleNodesFoundForNodeDef',\n nodeNotFoundForNodeDef: 'expression.nodeNotFoundForNodeDef',\n notSupported: 'expression.notSupported',\n regularExpressionInputTooLong: 'expression.regularExpressionInputTooLong',\n unaryOperatorNotSupported: 'expression.unaryOperatorNotSupported',\n unsafeRegularExpression: 'expression.unsafeRegularExpression',\n undefinedFunction: 'expression.undefinedFunction',\n unsupportedFunctionType: 'expression.unsupportedFunctionType',\n },\n geo: {\n pointNotFilled: 'geo.pointNotFilled',\n srsNotFound: 'geo.srsNotFound',\n transformFailed: 'geo.transformFailed',\n },\n job: {\n canceledOrErrorsFound: 'jobCanceledOrErrorsFound',\n },\n nodeDef: {\n hierarchyCircularDependency: 'nodeDef.hierarchyCircularDependency',\n parentNotFound: 'nodeDef.parentNotFound',\n },\n record: {\n dependencyOnRootFound: 'record.nodes.dependents.dependencyOnRootFound',\n enumeratorNodeNotFound: 'record.enumeratorNodeNotFound',\n multipleNodesFound: 'systemError.record.multipleNodesFound',\n nodeNotFound: 'record.nodeNotFound',\n nodesIndexNotInitialized: 'record.nodesIndexNotInitialized',\n updateSelfAndDependentsDefaultValues: 'record.updateSelfAndDependentsDefaultValues',\n updateSelfAndDependentsFileNames: 'record.updateSelfAndDependentsFileNames',\n },\n survey: {\n emptyNodeDefs: 'survey.emptyNodeDefs',\n nodeDefNameNotFound: 'survey.nodeDefNameNotFound',\n nodeDefUuidNotFound: 'survey.nodeDefUuidNotFound',\n rootDefNotFound: 'survey.rootDefNotFound',\n },\n} as const\n"]}
@@ -19,7 +19,9 @@ export const SystemErrorKeys = {
19
19
  multipleNodesFoundForNodeDef: 'expression.multipleNodesFoundForNodeDef',
20
20
  nodeNotFoundForNodeDef: 'expression.nodeNotFoundForNodeDef',
21
21
  notSupported: 'expression.notSupported',
22
+ regularExpressionInputTooLong: 'expression.regularExpressionInputTooLong',
22
23
  unaryOperatorNotSupported: 'expression.unaryOperatorNotSupported',
24
+ unsafeRegularExpression: 'expression.unsafeRegularExpression',
23
25
  undefinedFunction: 'expression.undefinedFunction',
24
26
  unsupportedFunctionType: 'expression.unsupportedFunctionType',
25
27
  },
@@ -1 +1 @@
1
- {"version":3,"file":"systemErrorKeys.js","sourceRoot":"","sources":["../../../src/error/systemErrorKeys.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,UAAU,EAAE;QACV,sBAAsB,EAAE,mCAAmC;QAC3D,2BAA2B,EAAE,wCAAwC;QACrE,0BAA0B,EAAE,uCAAuC;QACnE,2BAA2B,EAAE,wCAAwC;QACrE,kBAAkB,EAAE,+BAA+B;QACnD,iCAAiC,EAAE,8CAA8C;QACjF,iBAAiB,EAAE,8BAA8B;QACjD,wBAAwB,EAAE,qCAAqC;QAC/D,mBAAmB,EAAE,gCAAgC;QACrD,sCAAsC,EAAE,mDAAmD;QAC3F,wBAAwB,EAAE,qCAAqC;QAC/D,mBAAmB,EAAE,gCAAgC;QACrD,yBAAyB,EAAE,sCAAsC;QACjE,4BAA4B,EAAE,yCAAyC;QACvE,sBAAsB,EAAE,mCAAmC;QAC3D,YAAY,EAAE,yBAAyB;QACvC,yBAAyB,EAAE,sCAAsC;QACjE,iBAAiB,EAAE,8BAA8B;QACjD,uBAAuB,EAAE,oCAAoC;KAC9D;IACD,GAAG,EAAE;QACH,cAAc,EAAE,oBAAoB;QACpC,WAAW,EAAE,iBAAiB;QAC9B,eAAe,EAAE,qBAAqB;KACvC;IACD,GAAG,EAAE;QACH,qBAAqB,EAAE,0BAA0B;KAClD;IACD,OAAO,EAAE;QACP,2BAA2B,EAAE,qCAAqC;QAClE,cAAc,EAAE,wBAAwB;KACzC;IACD,MAAM,EAAE;QACN,qBAAqB,EAAE,+CAA+C;QACtE,sBAAsB,EAAE,+BAA+B;QACvD,kBAAkB,EAAE,uCAAuC;QAC3D,YAAY,EAAE,qBAAqB;QACnC,wBAAwB,EAAE,iCAAiC;QAC3D,oCAAoC,EAAE,6CAA6C;QACnF,gCAAgC,EAAE,yCAAyC;KAC5E;IACD,MAAM,EAAE;QACN,aAAa,EAAE,sBAAsB;QACrC,mBAAmB,EAAE,4BAA4B;QACjD,mBAAmB,EAAE,4BAA4B;QACjD,eAAe,EAAE,wBAAwB;KAC1C;CACO,CAAA","sourcesContent":["/**\n * Keys of the errors thrown by arena-core as SystemError (translatable, see SystemError.key).\n */\nexport const SystemErrorKeys = {\n expression: {\n areaOfInterestNotFound: 'expression.areaOfInterestNotFound',\n booleanOperatorNotSupported: 'expression.booleanOperatorNotSupported',\n functionHasTooFewArguments: 'expression.functionHasTooFewArguments',\n functionHasTooManyArguments: 'expression.functionHasTooManyArguments',\n identifierNotFound: 'expression.identifierNotFound',\n invalidAttributeValuePropertyName: 'expression.invalidAttributeValuePropertyName',\n invalidCalleeType: 'expression.invalidCalleeType',\n invalidCategoryExtraProp: 'expression.invalidCategoryExtraProp',\n invalidCategoryName: 'expression.invalidCategoryName',\n invalidTaxonVernacularNameLanguageCode: 'expression.invalidTaxonVernacularNameLanguageCode',\n invalidTaxonomyExtraProp: 'expression.invalidTaxonomyExtraProp',\n invalidTaxonomyName: 'expression.invalidTaxonomyName',\n missingFunctionParameters: 'expression.missingFunctionParameters',\n multipleNodesFoundForNodeDef: 'expression.multipleNodesFoundForNodeDef',\n nodeNotFoundForNodeDef: 'expression.nodeNotFoundForNodeDef',\n notSupported: 'expression.notSupported',\n unaryOperatorNotSupported: 'expression.unaryOperatorNotSupported',\n undefinedFunction: 'expression.undefinedFunction',\n unsupportedFunctionType: 'expression.unsupportedFunctionType',\n },\n geo: {\n pointNotFilled: 'geo.pointNotFilled',\n srsNotFound: 'geo.srsNotFound',\n transformFailed: 'geo.transformFailed',\n },\n job: {\n canceledOrErrorsFound: 'jobCanceledOrErrorsFound',\n },\n nodeDef: {\n hierarchyCircularDependency: 'nodeDef.hierarchyCircularDependency',\n parentNotFound: 'nodeDef.parentNotFound',\n },\n record: {\n dependencyOnRootFound: 'record.nodes.dependents.dependencyOnRootFound',\n enumeratorNodeNotFound: 'record.enumeratorNodeNotFound',\n multipleNodesFound: 'systemError.record.multipleNodesFound',\n nodeNotFound: 'record.nodeNotFound',\n nodesIndexNotInitialized: 'record.nodesIndexNotInitialized',\n updateSelfAndDependentsDefaultValues: 'record.updateSelfAndDependentsDefaultValues',\n updateSelfAndDependentsFileNames: 'record.updateSelfAndDependentsFileNames',\n },\n survey: {\n emptyNodeDefs: 'survey.emptyNodeDefs',\n nodeDefNameNotFound: 'survey.nodeDefNameNotFound',\n nodeDefUuidNotFound: 'survey.nodeDefUuidNotFound',\n rootDefNotFound: 'survey.rootDefNotFound',\n },\n} as const\n"]}
1
+ {"version":3,"file":"systemErrorKeys.js","sourceRoot":"","sources":["../../../src/error/systemErrorKeys.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,UAAU,EAAE;QACV,sBAAsB,EAAE,mCAAmC;QAC3D,2BAA2B,EAAE,wCAAwC;QACrE,0BAA0B,EAAE,uCAAuC;QACnE,2BAA2B,EAAE,wCAAwC;QACrE,kBAAkB,EAAE,+BAA+B;QACnD,iCAAiC,EAAE,8CAA8C;QACjF,iBAAiB,EAAE,8BAA8B;QACjD,wBAAwB,EAAE,qCAAqC;QAC/D,mBAAmB,EAAE,gCAAgC;QACrD,sCAAsC,EAAE,mDAAmD;QAC3F,wBAAwB,EAAE,qCAAqC;QAC/D,mBAAmB,EAAE,gCAAgC;QACrD,yBAAyB,EAAE,sCAAsC;QACjE,4BAA4B,EAAE,yCAAyC;QACvE,sBAAsB,EAAE,mCAAmC;QAC3D,YAAY,EAAE,yBAAyB;QACvC,6BAA6B,EAAE,0CAA0C;QACzE,yBAAyB,EAAE,sCAAsC;QACjE,uBAAuB,EAAE,oCAAoC;QAC7D,iBAAiB,EAAE,8BAA8B;QACjD,uBAAuB,EAAE,oCAAoC;KAC9D;IACD,GAAG,EAAE;QACH,cAAc,EAAE,oBAAoB;QACpC,WAAW,EAAE,iBAAiB;QAC9B,eAAe,EAAE,qBAAqB;KACvC;IACD,GAAG,EAAE;QACH,qBAAqB,EAAE,0BAA0B;KAClD;IACD,OAAO,EAAE;QACP,2BAA2B,EAAE,qCAAqC;QAClE,cAAc,EAAE,wBAAwB;KACzC;IACD,MAAM,EAAE;QACN,qBAAqB,EAAE,+CAA+C;QACtE,sBAAsB,EAAE,+BAA+B;QACvD,kBAAkB,EAAE,uCAAuC;QAC3D,YAAY,EAAE,qBAAqB;QACnC,wBAAwB,EAAE,iCAAiC;QAC3D,oCAAoC,EAAE,6CAA6C;QACnF,gCAAgC,EAAE,yCAAyC;KAC5E;IACD,MAAM,EAAE;QACN,aAAa,EAAE,sBAAsB;QACrC,mBAAmB,EAAE,4BAA4B;QACjD,mBAAmB,EAAE,4BAA4B;QACjD,eAAe,EAAE,wBAAwB;KAC1C;CACO,CAAA","sourcesContent":["/**\n * Keys of the errors thrown by arena-core as SystemError (translatable, see SystemError.key).\n */\nexport const SystemErrorKeys = {\n expression: {\n areaOfInterestNotFound: 'expression.areaOfInterestNotFound',\n booleanOperatorNotSupported: 'expression.booleanOperatorNotSupported',\n functionHasTooFewArguments: 'expression.functionHasTooFewArguments',\n functionHasTooManyArguments: 'expression.functionHasTooManyArguments',\n identifierNotFound: 'expression.identifierNotFound',\n invalidAttributeValuePropertyName: 'expression.invalidAttributeValuePropertyName',\n invalidCalleeType: 'expression.invalidCalleeType',\n invalidCategoryExtraProp: 'expression.invalidCategoryExtraProp',\n invalidCategoryName: 'expression.invalidCategoryName',\n invalidTaxonVernacularNameLanguageCode: 'expression.invalidTaxonVernacularNameLanguageCode',\n invalidTaxonomyExtraProp: 'expression.invalidTaxonomyExtraProp',\n invalidTaxonomyName: 'expression.invalidTaxonomyName',\n missingFunctionParameters: 'expression.missingFunctionParameters',\n multipleNodesFoundForNodeDef: 'expression.multipleNodesFoundForNodeDef',\n nodeNotFoundForNodeDef: 'expression.nodeNotFoundForNodeDef',\n notSupported: 'expression.notSupported',\n regularExpressionInputTooLong: 'expression.regularExpressionInputTooLong',\n unaryOperatorNotSupported: 'expression.unaryOperatorNotSupported',\n unsafeRegularExpression: 'expression.unsafeRegularExpression',\n undefinedFunction: 'expression.undefinedFunction',\n unsupportedFunctionType: 'expression.unsupportedFunctionType',\n },\n geo: {\n pointNotFilled: 'geo.pointNotFilled',\n srsNotFound: 'geo.srsNotFound',\n transformFailed: 'geo.transformFailed',\n },\n job: {\n canceledOrErrorsFound: 'jobCanceledOrErrorsFound',\n },\n nodeDef: {\n hierarchyCircularDependency: 'nodeDef.hierarchyCircularDependency',\n parentNotFound: 'nodeDef.parentNotFound',\n },\n record: {\n dependencyOnRootFound: 'record.nodes.dependents.dependencyOnRootFound',\n enumeratorNodeNotFound: 'record.enumeratorNodeNotFound',\n multipleNodesFound: 'systemError.record.multipleNodesFound',\n nodeNotFound: 'record.nodeNotFound',\n nodesIndexNotInitialized: 'record.nodesIndexNotInitialized',\n updateSelfAndDependentsDefaultValues: 'record.updateSelfAndDependentsDefaultValues',\n updateSelfAndDependentsFileNames: 'record.updateSelfAndDependentsFileNames',\n },\n survey: {\n emptyNodeDefs: 'survey.emptyNodeDefs',\n nodeDefNameNotFound: 'survey.nodeDefNameNotFound',\n nodeDefUuidNotFound: 'survey.nodeDefUuidNotFound',\n rootDefNotFound: 'survey.rootDefNotFound',\n },\n} as const\n"]}
@@ -10,6 +10,20 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import { SystemError, SystemErrorKeys } from '../../../error';
11
11
  import { ExpressionNodeEvaluator, ExpressionNodeType, } from '../../node';
12
12
  import { getGlobalObjectProperty } from '../global';
13
+ import { REG_EXP_INPUT_MAX_LENGTH } from '../regExpSafety';
14
+ // e.g. /.../.test(text) or text.match(/.../): the time taken by a regular expression grows with the input length
15
+ const checkRegExpInputLength = (fnObject, args) => {
16
+ const values = [fnObject, ...args];
17
+ if (!values.some((value) => value instanceof RegExp))
18
+ return;
19
+ const inputTooLong = values.find((value) => typeof value === 'string' && value.length > REG_EXP_INPUT_MAX_LENGTH);
20
+ if (inputTooLong !== undefined) {
21
+ throw new SystemError(SystemErrorKeys.expression.regularExpressionInputTooLong, {
22
+ maxLength: REG_EXP_INPUT_MAX_LENGTH,
23
+ length: inputTooLong.length,
24
+ });
25
+ }
26
+ };
13
27
  export class CallEvaluator extends ExpressionNodeEvaluator {
14
28
  evaluate(expressionNode) {
15
29
  return __awaiter(this, void 0, void 0, function* () {
@@ -35,6 +49,7 @@ export class CallEvaluator extends ExpressionNodeEvaluator {
35
49
  const fnObject = yield this.evaluator.evaluateNode(calleeObj, this.context);
36
50
  const argsEvaluated = yield Promise.all(exprArgs.map((arg) => this.evaluator.evaluateNode(arg, this.context)));
37
51
  const args = argsEvaluated.flat();
52
+ checkRegExpInputLength(fnObject, args);
38
53
  return fn.call(fnObject, ...args);
39
54
  }
40
55
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"call.js","sourceRoot":"","sources":["../../../../../src/expression/javascript/node/call.ts"],"names":[],"mappings":"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","sourcesContent":["import { SystemError, SystemErrorKeys } from '../../../error'\nimport { ExpressionContext } from '../../context'\nimport { ExpressionFunction } from '../../function'\nimport {\n CallExpression,\n ExpressionNodeEvaluator,\n ExpressionNodeType,\n IdentifierExpression,\n MemberExpression,\n} from '../../node'\nimport { getGlobalObjectProperty } from '../global'\n\nexport class CallEvaluator<C extends ExpressionContext> extends ExpressionNodeEvaluator<C, CallExpression> {\n async evaluate(expressionNode: CallExpression): Promise<any> {\n const { callee } = expressionNode\n\n if (callee.type === ExpressionNodeType.Member) {\n return this.evaluateMember(expressionNode, callee)\n } else if (callee.type === ExpressionNodeType.Identifier) {\n return this.evaluateIdentifier(expressionNode, callee)\n }\n\n // No complex expressions may be put in place of a function body.\n // Only a plain identifier is allowed.\n throw new SystemError(SystemErrorKeys.expression.invalidCalleeType, { type: callee.type })\n }\n\n private async evaluateMember(expressionNode: CallExpression, callee: MemberExpression): Promise<any> {\n const { arguments: exprArgs } = expressionNode\n\n // global function (e.g. Math.round(...))\n const fn = await this.evaluator.evaluateNode(callee, this.context)\n if (fn) {\n const { object: calleeObj } = callee\n const fnObject = await this.evaluator.evaluateNode(calleeObj, this.context)\n const argsEvaluated = await Promise.all(exprArgs.map((arg) => this.evaluator.evaluateNode(arg, this.context)))\n const args = argsEvaluated.flat()\n return fn.call(fnObject, ...args)\n }\n return null\n }\n\n private async evaluateIdentifier(expressionNode: CallExpression, callee: IdentifierExpression): Promise<any> {\n // Arguments is a reserved word in strict mode\n const { arguments: exprArgs } = expressionNode\n const { object: contextObject } = this.context\n\n const { name: fnName } = callee\n\n const functionInfo = this.evaluator.functions[fnName]\n if (functionInfo) {\n // The function is among the custom functions.\n return this.evaluateCustomIdentifier(expressionNode, fnName)\n }\n // identifier is a global object\n const globalFn = getGlobalObjectProperty(fnName, contextObject)\n if (globalFn !== null) {\n // global functions like String, Number, must be invoked passing node value as argument, not the node itself\n const contextArg = { ...this.context, evaluateToNode: false }\n const args = await Promise.all(exprArgs.map((arg) => this.evaluator.evaluateNode(arg, contextArg)))\n return globalFn(...args)\n }\n\n throw new SystemError(SystemErrorKeys.expression.undefinedFunction, { name: fnName })\n }\n\n private async evaluateCustomIdentifier(expressionNode: CallExpression, fnName: string): Promise<any> {\n // Arguments is a reserved word in strict mode\n const { arguments: exprArgs } = expressionNode\n const numArgs = exprArgs.length\n\n const expressionFunction: ExpressionFunction<C> = this.evaluator.functions[fnName]\n\n const { minArity, maxArity, evaluateArgsToNodes, executor } = expressionFunction\n\n if (numArgs < minArity)\n throw new SystemError(SystemErrorKeys.expression.functionHasTooFewArguments, { fnName, minArity, numArgs })\n if (maxArity !== undefined && maxArity >= 0 && numArgs > maxArity)\n throw new SystemError(SystemErrorKeys.expression.functionHasTooManyArguments, { fnName, maxArity, numArgs })\n\n // evaluate arguments\n const argsContext = { ...this.context, evaluateToNode: evaluateArgsToNodes }\n const args = await Promise.all(exprArgs.map((arg) => this.evaluator.evaluateNode(arg, argsContext)))\n\n // Currently there are no side effects from function evaluation so it's\n // safe to call the function even when we're just parsing the expression\n // to find all identifiers being used.\n return executor(this.context)(...args)\n }\n}\n"]}
1
+ {"version":3,"file":"call.js","sourceRoot":"","sources":["../../../../../src/expression/javascript/node/call.ts"],"names":[],"mappings":"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","sourcesContent":["import { SystemError, SystemErrorKeys } from '../../../error'\nimport { ExpressionContext } from '../../context'\nimport { ExpressionFunction } from '../../function'\nimport {\n CallExpression,\n ExpressionNodeEvaluator,\n ExpressionNodeType,\n IdentifierExpression,\n MemberExpression,\n} from '../../node'\nimport { getGlobalObjectProperty } from '../global'\nimport { REG_EXP_INPUT_MAX_LENGTH } from '../regExpSafety'\n\n// e.g. /.../.test(text) or text.match(/.../): the time taken by a regular expression grows with the input length\nconst checkRegExpInputLength = (fnObject: any, args: any[]): void => {\n const values = [fnObject, ...args]\n if (!values.some((value) => value instanceof RegExp)) return\n const inputTooLong = values.find((value) => typeof value === 'string' && value.length > REG_EXP_INPUT_MAX_LENGTH)\n if (inputTooLong !== undefined) {\n throw new SystemError(SystemErrorKeys.expression.regularExpressionInputTooLong, {\n maxLength: REG_EXP_INPUT_MAX_LENGTH,\n length: inputTooLong.length,\n })\n }\n}\n\nexport class CallEvaluator<C extends ExpressionContext> extends ExpressionNodeEvaluator<C, CallExpression> {\n async evaluate(expressionNode: CallExpression): Promise<any> {\n const { callee } = expressionNode\n\n if (callee.type === ExpressionNodeType.Member) {\n return this.evaluateMember(expressionNode, callee)\n } else if (callee.type === ExpressionNodeType.Identifier) {\n return this.evaluateIdentifier(expressionNode, callee)\n }\n\n // No complex expressions may be put in place of a function body.\n // Only a plain identifier is allowed.\n throw new SystemError(SystemErrorKeys.expression.invalidCalleeType, { type: callee.type })\n }\n\n private async evaluateMember(expressionNode: CallExpression, callee: MemberExpression): Promise<any> {\n const { arguments: exprArgs } = expressionNode\n\n // global function (e.g. Math.round(...))\n const fn = await this.evaluator.evaluateNode(callee, this.context)\n if (fn) {\n const { object: calleeObj } = callee\n const fnObject = await this.evaluator.evaluateNode(calleeObj, this.context)\n const argsEvaluated = await Promise.all(exprArgs.map((arg) => this.evaluator.evaluateNode(arg, this.context)))\n const args = argsEvaluated.flat()\n checkRegExpInputLength(fnObject, args)\n return fn.call(fnObject, ...args)\n }\n return null\n }\n\n private async evaluateIdentifier(expressionNode: CallExpression, callee: IdentifierExpression): Promise<any> {\n // Arguments is a reserved word in strict mode\n const { arguments: exprArgs } = expressionNode\n const { object: contextObject } = this.context\n\n const { name: fnName } = callee\n\n const functionInfo = this.evaluator.functions[fnName]\n if (functionInfo) {\n // The function is among the custom functions.\n return this.evaluateCustomIdentifier(expressionNode, fnName)\n }\n // identifier is a global object\n const globalFn = getGlobalObjectProperty(fnName, contextObject)\n if (globalFn !== null) {\n // global functions like String, Number, must be invoked passing node value as argument, not the node itself\n const contextArg = { ...this.context, evaluateToNode: false }\n const args = await Promise.all(exprArgs.map((arg) => this.evaluator.evaluateNode(arg, contextArg)))\n return globalFn(...args)\n }\n\n throw new SystemError(SystemErrorKeys.expression.undefinedFunction, { name: fnName })\n }\n\n private async evaluateCustomIdentifier(expressionNode: CallExpression, fnName: string): Promise<any> {\n // Arguments is a reserved word in strict mode\n const { arguments: exprArgs } = expressionNode\n const numArgs = exprArgs.length\n\n const expressionFunction: ExpressionFunction<C> = this.evaluator.functions[fnName]\n\n const { minArity, maxArity, evaluateArgsToNodes, executor } = expressionFunction\n\n if (numArgs < minArity)\n throw new SystemError(SystemErrorKeys.expression.functionHasTooFewArguments, { fnName, minArity, numArgs })\n if (maxArity !== undefined && maxArity >= 0 && numArgs > maxArity)\n throw new SystemError(SystemErrorKeys.expression.functionHasTooManyArguments, { fnName, maxArity, numArgs })\n\n // evaluate arguments\n const argsContext = { ...this.context, evaluateToNode: evaluateArgsToNodes }\n const args = await Promise.all(exprArgs.map((arg) => this.evaluator.evaluateNode(arg, argsContext)))\n\n // Currently there are no side effects from function evaluation so it's\n // safe to call the function even when we're just parsing the expression\n // to find all identifiers being used.\n return executor(this.context)(...args)\n }\n}\n"]}
@@ -1,7 +1,13 @@
1
+ import { SystemError, SystemErrorKeys } from '../../../error';
1
2
  import { ExpressionNodeEvaluator } from '../../node';
3
+ import { hasNestedQuantifiers } from '../regExpSafety';
2
4
  export class LiteralEvaluator extends ExpressionNodeEvaluator {
3
5
  evaluate(expressionNode) {
4
- return Promise.resolve(expressionNode.value);
6
+ const { value } = expressionNode;
7
+ if (value instanceof RegExp && hasNestedQuantifiers(value.source)) {
8
+ return Promise.reject(new SystemError(SystemErrorKeys.expression.unsafeRegularExpression, { pattern: value.source }));
9
+ }
10
+ return Promise.resolve(value);
5
11
  }
6
12
  }
7
13
  //# sourceMappingURL=literal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"literal.js","sourceRoot":"","sources":["../../../../../src/expression/javascript/node/literal.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAqB,MAAM,YAAY,CAAA;AAEvE,MAAM,OAAO,gBAA8C,SAAQ,uBAA6C;IAC9G,QAAQ,CAAC,cAAiC;QACxC,OAAO,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAA;IAC9C,CAAC;CACF","sourcesContent":["import { ExpressionContext } from '../../context'\nimport { ExpressionNodeEvaluator, LiteralExpression } from '../../node'\n\nexport class LiteralEvaluator<C extends ExpressionContext> extends ExpressionNodeEvaluator<C, LiteralExpression> {\n evaluate(expressionNode: LiteralExpression): Promise<any> {\n return Promise.resolve(expressionNode.value)\n }\n}\n"]}
1
+ {"version":3,"file":"literal.js","sourceRoot":"","sources":["../../../../../src/expression/javascript/node/literal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAE7D,OAAO,EAAE,uBAAuB,EAAqB,MAAM,YAAY,CAAA;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AAEtD,MAAM,OAAO,gBAA8C,SAAQ,uBAA6C;IAC9G,QAAQ,CAAC,cAAiC;QACxC,MAAM,EAAE,KAAK,EAAE,GAAG,cAAc,CAAA;QAChC,IAAI,KAAK,YAAY,MAAM,IAAI,oBAAoB,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YAClE,OAAO,OAAO,CAAC,MAAM,CACnB,IAAI,WAAW,CAAC,eAAe,CAAC,UAAU,CAAC,uBAAuB,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAC/F,CAAA;QACH,CAAC;QACD,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IAC/B,CAAC;CACF","sourcesContent":["import { SystemError, SystemErrorKeys } from '../../../error'\nimport { ExpressionContext } from '../../context'\nimport { ExpressionNodeEvaluator, LiteralExpression } from '../../node'\nimport { hasNestedQuantifiers } from '../regExpSafety'\n\nexport class LiteralEvaluator<C extends ExpressionContext> extends ExpressionNodeEvaluator<C, LiteralExpression> {\n evaluate(expressionNode: LiteralExpression): Promise<any> {\n const { value } = expressionNode\n if (value instanceof RegExp && hasNestedQuantifiers(value.source)) {\n return Promise.reject(\n new SystemError(SystemErrorKeys.expression.unsafeRegularExpression, { pattern: value.source })\n )\n }\n return Promise.resolve(value)\n }\n}\n"]}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Protection against regular expressions that can take exponential time (ReDoS): JavaScript cannot interrupt a
3
+ * running regular expression, so a single evaluation could freeze the server or the browser.
4
+ */
5
+ // maximum length of the strings that regular expressions are applied to in expressions
6
+ export const REG_EXP_INPUT_MAX_LENGTH = 1000;
7
+ // unbounded quantifier at the given position: *, + or {n,} (quantifiers like {n} or {n,m} are bounded)
8
+ const unboundedQuantifierRegExp = /^(\*|\+|\{\d+,\})/;
9
+ const isQuantifierAt = (source, index) => {
10
+ const char = source[index];
11
+ if (char === '*' || char === '+')
12
+ return true;
13
+ // {n,m} or {n,} (exact {n} repetitions don't multiply the ways a string can be matched)
14
+ return char === '{' && /^\{\d+,\d*\}/.test(source.substring(index));
15
+ };
16
+ const skipEscape = (index) => index + 2;
17
+ const skipCharacterClass = (source, index) => {
18
+ let i = index + 1;
19
+ while (i < source.length && source[i] !== ']') {
20
+ i = source[i] === '\\' ? skipEscape(i) : i + 1;
21
+ }
22
+ return i + 1;
23
+ };
24
+ // marks the innermost open group (if any) as containing a quantifier
25
+ const markInnermostGroupQuantified = (groupsStack) => {
26
+ if (groupsStack.length > 0) {
27
+ groupsStack[groupsStack.length - 1] = true;
28
+ }
29
+ };
30
+ /**
31
+ * Closes the group ending at the specified index (position of the ")").
32
+ * Returns true if the group contains a quantifier and it's repeated by an unbounded quantifier.
33
+ */
34
+ const closeGroup = (source, index, groupsStack) => {
35
+ var _a;
36
+ const groupContainsQuantifier = (_a = groupsStack.pop()) !== null && _a !== void 0 ? _a : false;
37
+ if (groupContainsQuantifier && unboundedQuantifierRegExp.test(source.substring(index + 1))) {
38
+ return true;
39
+ }
40
+ if (groupContainsQuantifier || isQuantifierAt(source, index + 1)) {
41
+ markInnermostGroupQuantified(groupsStack);
42
+ }
43
+ return false;
44
+ };
45
+ /**
46
+ * Returns true if the specified regular expression source contains a group repeated by an unbounded quantifier
47
+ * that contains a quantifier itself (star height > 1), e.g. (a+)+, (\w*)* or (x{1,3})+:
48
+ * these patterns can take exponential time on non-matching strings.
49
+ * Overlapping alternations like (a|aa)+ are not detected.
50
+ */
51
+ export const hasNestedQuantifiers = (source) => {
52
+ // for each open group: true if it contains a quantifier
53
+ const groupsStack = [];
54
+ let i = 0;
55
+ while (i < source.length) {
56
+ switch (source[i]) {
57
+ case '\\':
58
+ i = skipEscape(i);
59
+ break;
60
+ case '[':
61
+ i = skipCharacterClass(source, i);
62
+ break;
63
+ case '(':
64
+ groupsStack.push(false);
65
+ // a "?" right after "(" introduces a group modifier (e.g. "(?:"), it's not a quantifier
66
+ i += source[i + 1] === '?' ? 2 : 1;
67
+ break;
68
+ case ')':
69
+ if (closeGroup(source, i, groupsStack))
70
+ return true;
71
+ i += 1;
72
+ break;
73
+ default:
74
+ if (isQuantifierAt(source, i)) {
75
+ markInnermostGroupQuantified(groupsStack);
76
+ }
77
+ i += 1;
78
+ }
79
+ }
80
+ return false;
81
+ };
82
+ //# sourceMappingURL=regExpSafety.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regExpSafety.js","sourceRoot":"","sources":["../../../../src/expression/javascript/regExpSafety.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,uFAAuF;AACvF,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,CAAA;AAE5C,uGAAuG;AACvG,MAAM,yBAAyB,GAAG,mBAAmB,CAAA;AAErD,MAAM,cAAc,GAAG,CAAC,MAAc,EAAE,KAAa,EAAW,EAAE;IAChE,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IAC1B,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,IAAI,CAAA;IAC7C,wFAAwF;IACxF,OAAO,IAAI,KAAK,GAAG,IAAI,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAA;AACrE,CAAC,CAAA;AAED,MAAM,UAAU,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,KAAK,GAAG,CAAC,CAAA;AAEvD,MAAM,kBAAkB,GAAG,CAAC,MAAc,EAAE,KAAa,EAAU,EAAE;IACnE,IAAI,CAAC,GAAG,KAAK,GAAG,CAAC,CAAA;IACjB,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;QAC9C,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IAChD,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,CAAA;AACd,CAAC,CAAA;AAED,qEAAqE;AACrE,MAAM,4BAA4B,GAAG,CAAC,WAAsB,EAAQ,EAAE;IACpE,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,WAAW,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,CAAA;IAC5C,CAAC;AACH,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,UAAU,GAAG,CAAC,MAAc,EAAE,KAAa,EAAE,WAAsB,EAAW,EAAE;;IACpF,MAAM,uBAAuB,SAAG,WAAW,CAAC,GAAG,EAAE,mCAAI,KAAK,CAAA;IAC1D,IAAI,uBAAuB,IAAI,yBAAyB,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3F,OAAO,IAAI,CAAA;IACb,CAAC;IACD,IAAI,uBAAuB,IAAI,cAAc,CAAC,MAAM,EAAE,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC;QACjE,4BAA4B,CAAC,WAAW,CAAC,CAAA;IAC3C,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,MAAc,EAAW,EAAE;IAC9D,wDAAwD;IACxD,MAAM,WAAW,GAAc,EAAE,CAAA;IACjC,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;QACzB,QAAQ,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;YAClB,KAAK,IAAI;gBACP,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAA;gBACjB,MAAK;YACP,KAAK,GAAG;gBACN,CAAC,GAAG,kBAAkB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;gBACjC,MAAK;YACP,KAAK,GAAG;gBACN,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBACvB,wFAAwF;gBACxF,CAAC,IAAI,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;gBAClC,MAAK;YACP,KAAK,GAAG;gBACN,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,WAAW,CAAC;oBAAE,OAAO,IAAI,CAAA;gBACnD,CAAC,IAAI,CAAC,CAAA;gBACN,MAAK;YACP;gBACE,IAAI,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC;oBAC9B,4BAA4B,CAAC,WAAW,CAAC,CAAA;gBAC3C,CAAC;gBACD,CAAC,IAAI,CAAC,CAAA;QACV,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC,CAAA","sourcesContent":["/**\n * Protection against regular expressions that can take exponential time (ReDoS): JavaScript cannot interrupt a\n * running regular expression, so a single evaluation could freeze the server or the browser.\n */\n\n// maximum length of the strings that regular expressions are applied to in expressions\nexport const REG_EXP_INPUT_MAX_LENGTH = 1000\n\n// unbounded quantifier at the given position: *, + or {n,} (quantifiers like {n} or {n,m} are bounded)\nconst unboundedQuantifierRegExp = /^(\\*|\\+|\\{\\d+,\\})/\n\nconst isQuantifierAt = (source: string, index: number): boolean => {\n const char = source[index]\n if (char === '*' || char === '+') return true\n // {n,m} or {n,} (exact {n} repetitions don't multiply the ways a string can be matched)\n return char === '{' && /^\\{\\d+,\\d*\\}/.test(source.substring(index))\n}\n\nconst skipEscape = (index: number): number => index + 2\n\nconst skipCharacterClass = (source: string, index: number): number => {\n let i = index + 1\n while (i < source.length && source[i] !== ']') {\n i = source[i] === '\\\\' ? skipEscape(i) : i + 1\n }\n return i + 1\n}\n\n// marks the innermost open group (if any) as containing a quantifier\nconst markInnermostGroupQuantified = (groupsStack: boolean[]): void => {\n if (groupsStack.length > 0) {\n groupsStack[groupsStack.length - 1] = true\n }\n}\n\n/**\n * Closes the group ending at the specified index (position of the \")\").\n * Returns true if the group contains a quantifier and it's repeated by an unbounded quantifier.\n */\nconst closeGroup = (source: string, index: number, groupsStack: boolean[]): boolean => {\n const groupContainsQuantifier = groupsStack.pop() ?? false\n if (groupContainsQuantifier && unboundedQuantifierRegExp.test(source.substring(index + 1))) {\n return true\n }\n if (groupContainsQuantifier || isQuantifierAt(source, index + 1)) {\n markInnermostGroupQuantified(groupsStack)\n }\n return false\n}\n\n/**\n * Returns true if the specified regular expression source contains a group repeated by an unbounded quantifier\n * that contains a quantifier itself (star height > 1), e.g. (a+)+, (\\w*)* or (x{1,3})+:\n * these patterns can take exponential time on non-matching strings.\n * Overlapping alternations like (a|aa)+ are not detected.\n */\nexport const hasNestedQuantifiers = (source: string): boolean => {\n // for each open group: true if it contains a quantifier\n const groupsStack: boolean[] = []\n let i = 0\n while (i < source.length) {\n switch (source[i]) {\n case '\\\\':\n i = skipEscape(i)\n break\n case '[':\n i = skipCharacterClass(source, i)\n break\n case '(':\n groupsStack.push(false)\n // a \"?\" right after \"(\" introduces a group modifier (e.g. \"(?:\"), it's not a quantifier\n i += source[i + 1] === '?' ? 2 : 1\n break\n case ')':\n if (closeGroup(source, i, groupsStack)) return true\n i += 1\n break\n default:\n if (isQuantifierAt(source, i)) {\n markInnermostGroupQuantified(groupsStack)\n }\n i += 1\n }\n }\n return false\n}\n"]}
@@ -13,6 +13,20 @@ exports.CallEvaluator = void 0;
13
13
  const error_1 = require("../../../error");
14
14
  const node_1 = require("../../node");
15
15
  const global_1 = require("../global");
16
+ const regExpSafety_1 = require("../regExpSafety");
17
+ // e.g. /.../.test(text) or text.match(/.../): the time taken by a regular expression grows with the input length
18
+ const checkRegExpInputLength = (fnObject, args) => {
19
+ const values = [fnObject, ...args];
20
+ if (!values.some((value) => value instanceof RegExp))
21
+ return;
22
+ const inputTooLong = values.find((value) => typeof value === 'string' && value.length > regExpSafety_1.REG_EXP_INPUT_MAX_LENGTH);
23
+ if (inputTooLong !== undefined) {
24
+ throw new error_1.SystemError(error_1.SystemErrorKeys.expression.regularExpressionInputTooLong, {
25
+ maxLength: regExpSafety_1.REG_EXP_INPUT_MAX_LENGTH,
26
+ length: inputTooLong.length,
27
+ });
28
+ }
29
+ };
16
30
  class CallEvaluator extends node_1.ExpressionNodeEvaluator {
17
31
  evaluate(expressionNode) {
18
32
  return __awaiter(this, void 0, void 0, function* () {
@@ -38,6 +52,7 @@ class CallEvaluator extends node_1.ExpressionNodeEvaluator {
38
52
  const fnObject = yield this.evaluator.evaluateNode(calleeObj, this.context);
39
53
  const argsEvaluated = yield Promise.all(exprArgs.map((arg) => this.evaluator.evaluateNode(arg, this.context)));
40
54
  const args = argsEvaluated.flat();
55
+ checkRegExpInputLength(fnObject, args);
41
56
  return fn.call(fnObject, ...args);
42
57
  }
43
58
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"call.js","sourceRoot":"","sources":["../../../../src/expression/javascript/node/call.ts"],"names":[],"mappings":"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","sourcesContent":["import { SystemError, SystemErrorKeys } from '../../../error'\nimport { ExpressionContext } from '../../context'\nimport { ExpressionFunction } from '../../function'\nimport {\n CallExpression,\n ExpressionNodeEvaluator,\n ExpressionNodeType,\n IdentifierExpression,\n MemberExpression,\n} from '../../node'\nimport { getGlobalObjectProperty } from '../global'\n\nexport class CallEvaluator<C extends ExpressionContext> extends ExpressionNodeEvaluator<C, CallExpression> {\n async evaluate(expressionNode: CallExpression): Promise<any> {\n const { callee } = expressionNode\n\n if (callee.type === ExpressionNodeType.Member) {\n return this.evaluateMember(expressionNode, callee)\n } else if (callee.type === ExpressionNodeType.Identifier) {\n return this.evaluateIdentifier(expressionNode, callee)\n }\n\n // No complex expressions may be put in place of a function body.\n // Only a plain identifier is allowed.\n throw new SystemError(SystemErrorKeys.expression.invalidCalleeType, { type: callee.type })\n }\n\n private async evaluateMember(expressionNode: CallExpression, callee: MemberExpression): Promise<any> {\n const { arguments: exprArgs } = expressionNode\n\n // global function (e.g. Math.round(...))\n const fn = await this.evaluator.evaluateNode(callee, this.context)\n if (fn) {\n const { object: calleeObj } = callee\n const fnObject = await this.evaluator.evaluateNode(calleeObj, this.context)\n const argsEvaluated = await Promise.all(exprArgs.map((arg) => this.evaluator.evaluateNode(arg, this.context)))\n const args = argsEvaluated.flat()\n return fn.call(fnObject, ...args)\n }\n return null\n }\n\n private async evaluateIdentifier(expressionNode: CallExpression, callee: IdentifierExpression): Promise<any> {\n // Arguments is a reserved word in strict mode\n const { arguments: exprArgs } = expressionNode\n const { object: contextObject } = this.context\n\n const { name: fnName } = callee\n\n const functionInfo = this.evaluator.functions[fnName]\n if (functionInfo) {\n // The function is among the custom functions.\n return this.evaluateCustomIdentifier(expressionNode, fnName)\n }\n // identifier is a global object\n const globalFn = getGlobalObjectProperty(fnName, contextObject)\n if (globalFn !== null) {\n // global functions like String, Number, must be invoked passing node value as argument, not the node itself\n const contextArg = { ...this.context, evaluateToNode: false }\n const args = await Promise.all(exprArgs.map((arg) => this.evaluator.evaluateNode(arg, contextArg)))\n return globalFn(...args)\n }\n\n throw new SystemError(SystemErrorKeys.expression.undefinedFunction, { name: fnName })\n }\n\n private async evaluateCustomIdentifier(expressionNode: CallExpression, fnName: string): Promise<any> {\n // Arguments is a reserved word in strict mode\n const { arguments: exprArgs } = expressionNode\n const numArgs = exprArgs.length\n\n const expressionFunction: ExpressionFunction<C> = this.evaluator.functions[fnName]\n\n const { minArity, maxArity, evaluateArgsToNodes, executor } = expressionFunction\n\n if (numArgs < minArity)\n throw new SystemError(SystemErrorKeys.expression.functionHasTooFewArguments, { fnName, minArity, numArgs })\n if (maxArity !== undefined && maxArity >= 0 && numArgs > maxArity)\n throw new SystemError(SystemErrorKeys.expression.functionHasTooManyArguments, { fnName, maxArity, numArgs })\n\n // evaluate arguments\n const argsContext = { ...this.context, evaluateToNode: evaluateArgsToNodes }\n const args = await Promise.all(exprArgs.map((arg) => this.evaluator.evaluateNode(arg, argsContext)))\n\n // Currently there are no side effects from function evaluation so it's\n // safe to call the function even when we're just parsing the expression\n // to find all identifiers being used.\n return executor(this.context)(...args)\n }\n}\n"]}
1
+ {"version":3,"file":"call.js","sourceRoot":"","sources":["../../../../src/expression/javascript/node/call.ts"],"names":[],"mappings":"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","sourcesContent":["import { SystemError, SystemErrorKeys } from '../../../error'\nimport { ExpressionContext } from '../../context'\nimport { ExpressionFunction } from '../../function'\nimport {\n CallExpression,\n ExpressionNodeEvaluator,\n ExpressionNodeType,\n IdentifierExpression,\n MemberExpression,\n} from '../../node'\nimport { getGlobalObjectProperty } from '../global'\nimport { REG_EXP_INPUT_MAX_LENGTH } from '../regExpSafety'\n\n// e.g. /.../.test(text) or text.match(/.../): the time taken by a regular expression grows with the input length\nconst checkRegExpInputLength = (fnObject: any, args: any[]): void => {\n const values = [fnObject, ...args]\n if (!values.some((value) => value instanceof RegExp)) return\n const inputTooLong = values.find((value) => typeof value === 'string' && value.length > REG_EXP_INPUT_MAX_LENGTH)\n if (inputTooLong !== undefined) {\n throw new SystemError(SystemErrorKeys.expression.regularExpressionInputTooLong, {\n maxLength: REG_EXP_INPUT_MAX_LENGTH,\n length: inputTooLong.length,\n })\n }\n}\n\nexport class CallEvaluator<C extends ExpressionContext> extends ExpressionNodeEvaluator<C, CallExpression> {\n async evaluate(expressionNode: CallExpression): Promise<any> {\n const { callee } = expressionNode\n\n if (callee.type === ExpressionNodeType.Member) {\n return this.evaluateMember(expressionNode, callee)\n } else if (callee.type === ExpressionNodeType.Identifier) {\n return this.evaluateIdentifier(expressionNode, callee)\n }\n\n // No complex expressions may be put in place of a function body.\n // Only a plain identifier is allowed.\n throw new SystemError(SystemErrorKeys.expression.invalidCalleeType, { type: callee.type })\n }\n\n private async evaluateMember(expressionNode: CallExpression, callee: MemberExpression): Promise<any> {\n const { arguments: exprArgs } = expressionNode\n\n // global function (e.g. Math.round(...))\n const fn = await this.evaluator.evaluateNode(callee, this.context)\n if (fn) {\n const { object: calleeObj } = callee\n const fnObject = await this.evaluator.evaluateNode(calleeObj, this.context)\n const argsEvaluated = await Promise.all(exprArgs.map((arg) => this.evaluator.evaluateNode(arg, this.context)))\n const args = argsEvaluated.flat()\n checkRegExpInputLength(fnObject, args)\n return fn.call(fnObject, ...args)\n }\n return null\n }\n\n private async evaluateIdentifier(expressionNode: CallExpression, callee: IdentifierExpression): Promise<any> {\n // Arguments is a reserved word in strict mode\n const { arguments: exprArgs } = expressionNode\n const { object: contextObject } = this.context\n\n const { name: fnName } = callee\n\n const functionInfo = this.evaluator.functions[fnName]\n if (functionInfo) {\n // The function is among the custom functions.\n return this.evaluateCustomIdentifier(expressionNode, fnName)\n }\n // identifier is a global object\n const globalFn = getGlobalObjectProperty(fnName, contextObject)\n if (globalFn !== null) {\n // global functions like String, Number, must be invoked passing node value as argument, not the node itself\n const contextArg = { ...this.context, evaluateToNode: false }\n const args = await Promise.all(exprArgs.map((arg) => this.evaluator.evaluateNode(arg, contextArg)))\n return globalFn(...args)\n }\n\n throw new SystemError(SystemErrorKeys.expression.undefinedFunction, { name: fnName })\n }\n\n private async evaluateCustomIdentifier(expressionNode: CallExpression, fnName: string): Promise<any> {\n // Arguments is a reserved word in strict mode\n const { arguments: exprArgs } = expressionNode\n const numArgs = exprArgs.length\n\n const expressionFunction: ExpressionFunction<C> = this.evaluator.functions[fnName]\n\n const { minArity, maxArity, evaluateArgsToNodes, executor } = expressionFunction\n\n if (numArgs < minArity)\n throw new SystemError(SystemErrorKeys.expression.functionHasTooFewArguments, { fnName, minArity, numArgs })\n if (maxArity !== undefined && maxArity >= 0 && numArgs > maxArity)\n throw new SystemError(SystemErrorKeys.expression.functionHasTooManyArguments, { fnName, maxArity, numArgs })\n\n // evaluate arguments\n const argsContext = { ...this.context, evaluateToNode: evaluateArgsToNodes }\n const args = await Promise.all(exprArgs.map((arg) => this.evaluator.evaluateNode(arg, argsContext)))\n\n // Currently there are no side effects from function evaluation so it's\n // safe to call the function even when we're just parsing the expression\n // to find all identifiers being used.\n return executor(this.context)(...args)\n }\n}\n"]}
@@ -1,10 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LiteralEvaluator = void 0;
4
+ const error_1 = require("../../../error");
4
5
  const node_1 = require("../../node");
6
+ const regExpSafety_1 = require("../regExpSafety");
5
7
  class LiteralEvaluator extends node_1.ExpressionNodeEvaluator {
6
8
  evaluate(expressionNode) {
7
- return Promise.resolve(expressionNode.value);
9
+ const { value } = expressionNode;
10
+ if (value instanceof RegExp && (0, regExpSafety_1.hasNestedQuantifiers)(value.source)) {
11
+ return Promise.reject(new error_1.SystemError(error_1.SystemErrorKeys.expression.unsafeRegularExpression, { pattern: value.source }));
12
+ }
13
+ return Promise.resolve(value);
8
14
  }
9
15
  }
10
16
  exports.LiteralEvaluator = LiteralEvaluator;
@@ -1 +1 @@
1
- {"version":3,"file":"literal.js","sourceRoot":"","sources":["../../../../src/expression/javascript/node/literal.ts"],"names":[],"mappings":";;;AACA,qCAAuE;AAEvE,sBAA2D,SAAQ,8BAA6C;IAC9G,QAAQ,CAAC,cAAiC;QACxC,OAAO,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAA;IAC9C,CAAC;CACF","sourcesContent":["import { ExpressionContext } from '../../context'\nimport { ExpressionNodeEvaluator, LiteralExpression } from '../../node'\n\nexport class LiteralEvaluator<C extends ExpressionContext> extends ExpressionNodeEvaluator<C, LiteralExpression> {\n evaluate(expressionNode: LiteralExpression): Promise<any> {\n return Promise.resolve(expressionNode.value)\n }\n}\n"]}
1
+ {"version":3,"file":"literal.js","sourceRoot":"","sources":["../../../../src/expression/javascript/node/literal.ts"],"names":[],"mappings":";;;AAAA,0CAA6D;AAE7D,qCAAuE;AACvE,kDAAsD;AAEtD,sBAA2D,SAAQ,8BAA6C;IAC9G,QAAQ,CAAC,cAAiC;QACxC,MAAM,EAAE,KAAK,EAAE,GAAG,cAAc,CAAA;QAChC,IAAI,KAAK,YAAY,MAAM,IAAI,IAAA,mCAAoB,EAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YAClE,OAAO,OAAO,CAAC,MAAM,CACnB,IAAI,mBAAW,CAAC,uBAAe,CAAC,UAAU,CAAC,uBAAuB,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAC/F,CAAA;QACH,CAAC;QACD,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IAC/B,CAAC;CACF","sourcesContent":["import { SystemError, SystemErrorKeys } from '../../../error'\nimport { ExpressionContext } from '../../context'\nimport { ExpressionNodeEvaluator, LiteralExpression } from '../../node'\nimport { hasNestedQuantifiers } from '../regExpSafety'\n\nexport class LiteralEvaluator<C extends ExpressionContext> extends ExpressionNodeEvaluator<C, LiteralExpression> {\n evaluate(expressionNode: LiteralExpression): Promise<any> {\n const { value } = expressionNode\n if (value instanceof RegExp && hasNestedQuantifiers(value.source)) {\n return Promise.reject(\n new SystemError(SystemErrorKeys.expression.unsafeRegularExpression, { pattern: value.source })\n )\n }\n return Promise.resolve(value)\n }\n}\n"]}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Protection against regular expressions that can take exponential time (ReDoS): JavaScript cannot interrupt a
3
+ * running regular expression, so a single evaluation could freeze the server or the browser.
4
+ */
5
+ export declare const REG_EXP_INPUT_MAX_LENGTH = 1000;
6
+ /**
7
+ * Returns true if the specified regular expression source contains a group repeated by an unbounded quantifier
8
+ * that contains a quantifier itself (star height > 1), e.g. (a+)+, (\w*)* or (x{1,3})+:
9
+ * these patterns can take exponential time on non-matching strings.
10
+ * Overlapping alternations like (a|aa)+ are not detected.
11
+ */
12
+ export declare const hasNestedQuantifiers: (source: string) => boolean;
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ /**
3
+ * Protection against regular expressions that can take exponential time (ReDoS): JavaScript cannot interrupt a
4
+ * running regular expression, so a single evaluation could freeze the server or the browser.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.hasNestedQuantifiers = exports.REG_EXP_INPUT_MAX_LENGTH = void 0;
8
+ // maximum length of the strings that regular expressions are applied to in expressions
9
+ exports.REG_EXP_INPUT_MAX_LENGTH = 1000;
10
+ // unbounded quantifier at the given position: *, + or {n,} (quantifiers like {n} or {n,m} are bounded)
11
+ const unboundedQuantifierRegExp = /^(\*|\+|\{\d+,\})/;
12
+ const isQuantifierAt = (source, index) => {
13
+ const char = source[index];
14
+ if (char === '*' || char === '+')
15
+ return true;
16
+ // {n,m} or {n,} (exact {n} repetitions don't multiply the ways a string can be matched)
17
+ return char === '{' && /^\{\d+,\d*\}/.test(source.substring(index));
18
+ };
19
+ const skipEscape = (index) => index + 2;
20
+ const skipCharacterClass = (source, index) => {
21
+ let i = index + 1;
22
+ while (i < source.length && source[i] !== ']') {
23
+ i = source[i] === '\\' ? skipEscape(i) : i + 1;
24
+ }
25
+ return i + 1;
26
+ };
27
+ // marks the innermost open group (if any) as containing a quantifier
28
+ const markInnermostGroupQuantified = (groupsStack) => {
29
+ if (groupsStack.length > 0) {
30
+ groupsStack[groupsStack.length - 1] = true;
31
+ }
32
+ };
33
+ /**
34
+ * Closes the group ending at the specified index (position of the ")").
35
+ * Returns true if the group contains a quantifier and it's repeated by an unbounded quantifier.
36
+ */
37
+ const closeGroup = (source, index, groupsStack) => {
38
+ var _a;
39
+ const groupContainsQuantifier = (_a = groupsStack.pop()) !== null && _a !== void 0 ? _a : false;
40
+ if (groupContainsQuantifier && unboundedQuantifierRegExp.test(source.substring(index + 1))) {
41
+ return true;
42
+ }
43
+ if (groupContainsQuantifier || isQuantifierAt(source, index + 1)) {
44
+ markInnermostGroupQuantified(groupsStack);
45
+ }
46
+ return false;
47
+ };
48
+ /**
49
+ * Returns true if the specified regular expression source contains a group repeated by an unbounded quantifier
50
+ * that contains a quantifier itself (star height > 1), e.g. (a+)+, (\w*)* or (x{1,3})+:
51
+ * these patterns can take exponential time on non-matching strings.
52
+ * Overlapping alternations like (a|aa)+ are not detected.
53
+ */
54
+ const hasNestedQuantifiers = (source) => {
55
+ // for each open group: true if it contains a quantifier
56
+ const groupsStack = [];
57
+ let i = 0;
58
+ while (i < source.length) {
59
+ switch (source[i]) {
60
+ case '\\':
61
+ i = skipEscape(i);
62
+ break;
63
+ case '[':
64
+ i = skipCharacterClass(source, i);
65
+ break;
66
+ case '(':
67
+ groupsStack.push(false);
68
+ // a "?" right after "(" introduces a group modifier (e.g. "(?:"), it's not a quantifier
69
+ i += source[i + 1] === '?' ? 2 : 1;
70
+ break;
71
+ case ')':
72
+ if (closeGroup(source, i, groupsStack))
73
+ return true;
74
+ i += 1;
75
+ break;
76
+ default:
77
+ if (isQuantifierAt(source, i)) {
78
+ markInnermostGroupQuantified(groupsStack);
79
+ }
80
+ i += 1;
81
+ }
82
+ }
83
+ return false;
84
+ };
85
+ exports.hasNestedQuantifiers = hasNestedQuantifiers;
86
+ //# sourceMappingURL=regExpSafety.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regExpSafety.js","sourceRoot":"","sources":["../../../src/expression/javascript/regExpSafety.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Protection against regular expressions that can take exponential time (ReDoS): JavaScript cannot interrupt a\n * running regular expression, so a single evaluation could freeze the server or the browser.\n */\n\n// maximum length of the strings that regular expressions are applied to in expressions\nexport const REG_EXP_INPUT_MAX_LENGTH = 1000\n\n// unbounded quantifier at the given position: *, + or {n,} (quantifiers like {n} or {n,m} are bounded)\nconst unboundedQuantifierRegExp = /^(\\*|\\+|\\{\\d+,\\})/\n\nconst isQuantifierAt = (source: string, index: number): boolean => {\n const char = source[index]\n if (char === '*' || char === '+') return true\n // {n,m} or {n,} (exact {n} repetitions don't multiply the ways a string can be matched)\n return char === '{' && /^\\{\\d+,\\d*\\}/.test(source.substring(index))\n}\n\nconst skipEscape = (index: number): number => index + 2\n\nconst skipCharacterClass = (source: string, index: number): number => {\n let i = index + 1\n while (i < source.length && source[i] !== ']') {\n i = source[i] === '\\\\' ? skipEscape(i) : i + 1\n }\n return i + 1\n}\n\n// marks the innermost open group (if any) as containing a quantifier\nconst markInnermostGroupQuantified = (groupsStack: boolean[]): void => {\n if (groupsStack.length > 0) {\n groupsStack[groupsStack.length - 1] = true\n }\n}\n\n/**\n * Closes the group ending at the specified index (position of the \")\").\n * Returns true if the group contains a quantifier and it's repeated by an unbounded quantifier.\n */\nconst closeGroup = (source: string, index: number, groupsStack: boolean[]): boolean => {\n const groupContainsQuantifier = groupsStack.pop() ?? false\n if (groupContainsQuantifier && unboundedQuantifierRegExp.test(source.substring(index + 1))) {\n return true\n }\n if (groupContainsQuantifier || isQuantifierAt(source, index + 1)) {\n markInnermostGroupQuantified(groupsStack)\n }\n return false\n}\n\n/**\n * Returns true if the specified regular expression source contains a group repeated by an unbounded quantifier\n * that contains a quantifier itself (star height > 1), e.g. (a+)+, (\\w*)* or (x{1,3})+:\n * these patterns can take exponential time on non-matching strings.\n * Overlapping alternations like (a|aa)+ are not detected.\n */\nexport const hasNestedQuantifiers = (source: string): boolean => {\n // for each open group: true if it contains a quantifier\n const groupsStack: boolean[] = []\n let i = 0\n while (i < source.length) {\n switch (source[i]) {\n case '\\\\':\n i = skipEscape(i)\n break\n case '[':\n i = skipCharacterClass(source, i)\n break\n case '(':\n groupsStack.push(false)\n // a \"?\" right after \"(\" introduces a group modifier (e.g. \"(?:\"), it's not a quantifier\n i += source[i + 1] === '?' ? 2 : 1\n break\n case ')':\n if (closeGroup(source, i, groupsStack)) return true\n i += 1\n break\n default:\n if (isQuantifierAt(source, i)) {\n markInnermostGroupQuantified(groupsStack)\n }\n i += 1\n }\n }\n return false\n}\n"]}
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "name": "OpenForis",
5
5
  "email": "openforis.arena@gmail.com"
6
6
  },
7
- "version": "2.17.0",
7
+ "version": "2.18.0",
8
8
  "description": "Arena core module",
9
9
  "repository": {
10
10
  "type": "git",