"use strict"; // Shared response-size limits for the IMAP parser. Kept in one place so the streaming parser // (ImapStream) and the standalone token parser cannot drift apart, and so the documented // defaults in the ImapFlowOptions type describe both paths. Object.defineProperty(exports, "__esModule", { value: true }); exports.createLiteralTooLargeError = exports.normalizeLimit = exports.boundedInput = exports.ERROR_CONTEXT_LENGTH = exports.MAX_RESPONSE_TOKENS = exports.MAX_RESPONSE_SIZE = exports.MAX_LINE_SIZE = exports.MAX_LITERAL_SIZE = void 0; const errors_js_1 = require("../errors.js"); // Maximum allowed literal size: 1GB (1073741824 bytes) exports.MAX_LITERAL_SIZE = 1024 * 1024 * 1024; // Default maximum length of a single line (a response without a literal). Matches the literal cap: // large literal-free responses (e.g. big SEARCH/LIST results) are legitimate, so this bound exists // only to stop a server that never sends a line terminator, not to constrain normal traffic. exports.MAX_LINE_SIZE = exports.MAX_LITERAL_SIZE; // Default maximum total size of a single assembled response: every line segment and literal of // one response combined. The per-line and per-literal caps alone cannot stop a server that // spreads attacker-controlled bytes across an unbounded number of tokens of a single response // (e.g. one FETCH answer carrying many maximum-size literals). // // Deliberately above the literal cap: the response total also carries the literal's marker line // and the rest of the response framing, so a cap equal to MAX_LITERAL_SIZE would make a literal // of exactly the maximum permitted size impossible to receive. Configuring both limits calls for // the same headroom - set maxResponseSize above maxLiteralSize, not equal to it. exports.MAX_RESPONSE_SIZE = 2 * exports.MAX_LITERAL_SIZE; // Default maximum number of tokens (atoms, strings, literals, lists and the other parse tree // nodes) in a single response. The byte limits bound what a server sends, not what parsing it // costs: every token becomes a tree node and an attribute object, around a hundred bytes of heap // for a two-byte "1 ", so a line of many small tokens costs fifty times its size. A legitimate // response stays far below this (the long one, a SEARCH answer of plain numbers, is read without // the tokenizer, see parser()), so the bound only stops a server that floods one response. exports.MAX_RESPONSE_TOKENS = 1000000; // How much of the offending input a parse error carries along. The error travels whole into log // entries (pino copies every property of a logged error) and into the rejection of the command // the line belonged to, and the line can be as long as the configured line cap. exports.ERROR_CONTEXT_LENGTH = 1024; /** * The input a parse error carries: a bounded prefix with the full length. * * @param input - The input that failed to parse * @returns The bounded prefix and the full length */ const boundedInput = (input) => ({ input: input.slice(0, exports.ERROR_CONTEXT_LENGTH), inputLength: input.length }); exports.boundedInput = boundedInput; /** * Normalizes a configured size limit. A non-negative integer is honored as-is (including 0, which * means "reject anything non-empty"), and `Infinity` disables the limit; anything else falls back * to the default, so an explicit 0 is not silently swallowed the way `value || DEFAULT` would * swallow it. * * @param value - The configured value. * @param defaultValue - Fallback when the value is not a usable limit. * @returns The normalized limit. */ const normalizeLimit = (value, defaultValue) => (Number.isInteger(value) || value === Infinity) && value >= 0 ? value : defaultValue; exports.normalizeLimit = normalizeLimit; /** * Builds the `LiteralTooLarge` error. One shape for every place a literal is refused, so callers * can rely on `code`, `literalSize` and `maxSize` regardless of which parser rejected it. * * @param literalSize - The declared literal size. * @param maxSize - The bound that was exceeded. * @param reason - What the bound was, when it is not the configured maximum. * @returns The error to emit or throw. */ const createLiteralTooLargeError = (literalSize, maxSize, reason) => (0, errors_js_1.createImapError)(`Literal size ${literalSize} exceeds ${reason || `maximum allowed size of ${maxSize} bytes`}`, 'LiteralTooLarge', { literalSize, maxSize }); exports.createLiteralTooLargeError = createLiteralTooLargeError;