Area restrita - Questionario

This commit is contained in:
2026-06-08 23:50:59 -03:00
parent f2e2400637
commit ef968f10ae
6972 changed files with 23454 additions and 2267883 deletions
+1 -9
View File
@@ -318,8 +318,7 @@ The following options may be used with the main `picomatch()` function or any of
| `keepQuotes` | `boolean` | `false` | Retain quotes in the generated regex, since quotes may also be used as an alternative to backslashes. |
| `literalBrackets` | `boolean` | `undefined` | When `true`, brackets in the glob pattern will be escaped so that only literal brackets will be matched. |
| `matchBase` | `boolean` | `false` | Alias for `basename` |
| `maxLength` | `number` | `65536` | Limit the max length of the input string. An error is thrown if the input string is longer than this value. |
| `maxExtglobRecursion` | `number\|boolean` | `0` | Limit nested quantified extglobs and other risky repeated extglob forms. When the limit is exceeded, the extglob is treated as a literal string instead of being compiled to regex. Set to `false` to disable this safeguard. |
| `maxLength` | `boolean` | `65536` | Limit the max length of the input string. An error is thrown if the input string is longer than this value. |
| `nobrace` | `boolean` | `false` | Disable brace matching, so that `{a,b}` and `{1..3}` would be treated as literal characters. |
| `nobracket` | `boolean` | `undefined` | Disable matching with regex brackets. |
| `nocase` | `boolean` | `false` | Make matching case-insensitive. Equivalent to the regex `i` flag. Note that this option is overridden by the `flags` option. |
@@ -534,13 +533,6 @@ console.log(pm.isMatch('foo.bar', '!(foo).!(bar)')); // false
// supports nested extglobs
console.log(pm.isMatch('foo.bar', '!(!(foo)).!(!(bar))')); // true
// risky quantified extglobs are treated literally by default
console.log(pm.makeRe('+(a|aa)'));
//=> /^(?:\+\(a\|aa\))$/
// increase the limit to allow a small amount of nested quantified extglobs
console.log(pm.isMatch('aaa', '+(+(a))', { maxExtglobRecursion: 1 })); // true
```
#### POSIX brackets
-5
View File
@@ -4,8 +4,6 @@ const path = require('path');
const WIN_SLASH = '\\\\/';
const WIN_NO_SLASH = `[^${WIN_SLASH}]`;
const DEFAULT_MAX_EXTGLOB_RECURSION = 0;
/**
* Posix glob regex
*/
@@ -69,7 +67,6 @@ const WINDOWS_CHARS = {
*/
const POSIX_REGEX_SOURCE = {
__proto__: null,
alnum: 'a-zA-Z0-9',
alpha: 'a-zA-Z',
ascii: '\\x00-\\x7F',
@@ -87,7 +84,6 @@ const POSIX_REGEX_SOURCE = {
};
module.exports = {
DEFAULT_MAX_EXTGLOB_RECURSION,
MAX_LENGTH: 1024 * 64,
POSIX_REGEX_SOURCE,
@@ -101,7 +97,6 @@ module.exports = {
// Replace globs with equivalent patterns to reduce parsing time.
REPLACEMENTS: {
__proto__: null,
'***': '*',
'**/**': '**',
'**/**/**': '**'
-301
View File
@@ -45,277 +45,6 @@ const syntaxError = (type, char) => {
return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`;
};
const splitTopLevel = input => {
const parts = [];
let bracket = 0;
let paren = 0;
let quote = 0;
let value = '';
let escaped = false;
for (const ch of input) {
if (escaped === true) {
value += ch;
escaped = false;
continue;
}
if (ch === '\\') {
value += ch;
escaped = true;
continue;
}
if (ch === '"') {
quote = quote === 1 ? 0 : 1;
value += ch;
continue;
}
if (quote === 0) {
if (ch === '[') {
bracket++;
} else if (ch === ']' && bracket > 0) {
bracket--;
} else if (bracket === 0) {
if (ch === '(') {
paren++;
} else if (ch === ')' && paren > 0) {
paren--;
} else if (ch === '|' && paren === 0) {
parts.push(value);
value = '';
continue;
}
}
}
value += ch;
}
parts.push(value);
return parts;
};
const isPlainBranch = branch => {
let escaped = false;
for (const ch of branch) {
if (escaped === true) {
escaped = false;
continue;
}
if (ch === '\\') {
escaped = true;
continue;
}
if (/[?*+@!()[\]{}]/.test(ch)) {
return false;
}
}
return true;
};
const normalizeSimpleBranch = branch => {
let value = branch.trim();
let changed = true;
while (changed === true) {
changed = false;
if (/^@\([^\\()[\]{}|]+\)$/.test(value)) {
value = value.slice(2, -1);
changed = true;
}
}
if (!isPlainBranch(value)) {
return;
}
return value.replace(/\\(.)/g, '$1');
};
const hasRepeatedCharPrefixOverlap = branches => {
const values = branches.map(normalizeSimpleBranch).filter(Boolean);
for (let i = 0; i < values.length; i++) {
for (let j = i + 1; j < values.length; j++) {
const a = values[i];
const b = values[j];
const char = a[0];
if (!char || a !== char.repeat(a.length) || b !== char.repeat(b.length)) {
continue;
}
if (a === b || a.startsWith(b) || b.startsWith(a)) {
return true;
}
}
}
return false;
};
const parseRepeatedExtglob = (pattern, requireEnd = true) => {
if ((pattern[0] !== '+' && pattern[0] !== '*') || pattern[1] !== '(') {
return;
}
let bracket = 0;
let paren = 0;
let quote = 0;
let escaped = false;
for (let i = 1; i < pattern.length; i++) {
const ch = pattern[i];
if (escaped === true) {
escaped = false;
continue;
}
if (ch === '\\') {
escaped = true;
continue;
}
if (ch === '"') {
quote = quote === 1 ? 0 : 1;
continue;
}
if (quote === 1) {
continue;
}
if (ch === '[') {
bracket++;
continue;
}
if (ch === ']' && bracket > 0) {
bracket--;
continue;
}
if (bracket > 0) {
continue;
}
if (ch === '(') {
paren++;
continue;
}
if (ch === ')') {
paren--;
if (paren === 0) {
if (requireEnd === true && i !== pattern.length - 1) {
return;
}
return {
type: pattern[0],
body: pattern.slice(2, i),
end: i
};
}
}
}
};
const getStarExtglobSequenceOutput = pattern => {
let index = 0;
const chars = [];
while (index < pattern.length) {
const match = parseRepeatedExtglob(pattern.slice(index), false);
if (!match || match.type !== '*') {
return;
}
const branches = splitTopLevel(match.body).map(branch => branch.trim());
if (branches.length !== 1) {
return;
}
const branch = normalizeSimpleBranch(branches[0]);
if (!branch || branch.length !== 1) {
return;
}
chars.push(branch);
index += match.end + 1;
}
if (chars.length < 1) {
return;
}
const source = chars.length === 1
? utils.escapeRegex(chars[0])
: `[${chars.map(ch => utils.escapeRegex(ch)).join('')}]`;
return `${source}*`;
};
const repeatedExtglobRecursion = pattern => {
let depth = 0;
let value = pattern.trim();
let match = parseRepeatedExtglob(value);
while (match) {
depth++;
value = match.body.trim();
match = parseRepeatedExtglob(value);
}
return depth;
};
const analyzeRepeatedExtglob = (body, options) => {
if (options.maxExtglobRecursion === false) {
return { risky: false };
}
const max =
typeof options.maxExtglobRecursion === 'number'
? options.maxExtglobRecursion
: constants.DEFAULT_MAX_EXTGLOB_RECURSION;
const branches = splitTopLevel(body).map(branch => branch.trim());
if (branches.length > 1) {
if (
branches.some(branch => branch === '') ||
branches.some(branch => /^[*?]+$/.test(branch)) ||
hasRepeatedCharPrefixOverlap(branches)
) {
return { risky: true };
}
}
for (const branch of branches) {
const safeOutput = getStarExtglobSequenceOutput(branch);
if (safeOutput) {
return { risky: true, safeOutput };
}
if (repeatedExtglobRecursion(branch) > max) {
return { risky: true };
}
}
return { risky: false };
};
/**
* Parse the given input string.
* @param {String} input
@@ -497,8 +226,6 @@ const parse = (input, options) => {
token.prev = prev;
token.parens = state.parens;
token.output = state.output;
token.startIndex = state.index;
token.tokensIndex = tokens.length;
const output = (opts.capture ? '(' : '') + token.open;
increment('parens');
@@ -508,34 +235,6 @@ const parse = (input, options) => {
};
const extglobClose = token => {
const literal = input.slice(token.startIndex, state.index + 1);
const body = input.slice(token.startIndex + 2, state.index);
const analysis = analyzeRepeatedExtglob(body, opts);
if ((token.type === 'plus' || token.type === 'star') && analysis.risky) {
const safeOutput = analysis.safeOutput
? (token.output ? '' : ONE_CHAR) + (opts.capture ? `(${analysis.safeOutput})` : analysis.safeOutput)
: undefined;
const open = tokens[token.tokensIndex];
open.type = 'text';
open.value = literal;
open.output = safeOutput || utils.escapeRegex(literal);
for (let i = token.tokensIndex + 1; i < tokens.length; i++) {
tokens[i].value = '';
tokens[i].output = '';
delete tokens[i].suffix;
}
state.output = token.output + open.output;
state.backtrack = true;
push({ type: 'paren', extglob: true, value, output: '' });
decrement('parens');
return;
}
let output = token.close + (opts.capture ? ')' : '');
let rest;
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "picomatch",
"description": "Blazing fast and accurate glob matcher written in JavaScript, with no dependencies and full support for standard and extended Bash glob features, including braces, extglobs, POSIX brackets, and regular expressions.",
"version": "2.3.2",
"version": "2.3.1",
"homepage": "https://github.com/micromatch/picomatch",
"author": "Jon Schlinkert (https://github.com/jonschlinkert)",
"funding": "https://github.com/sponsors/jonschlinkert",