Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,40 @@ function formatAjvErrors (errors) {
return stringErrors
}

/**
* Computes the TTL in seconds from an expiry date or a number of seconds.
* Returns undefined if no expiry is provided.
*
* @private
* @param {Date|number} expiry a Date object or seconds from now
* @returns {number|undefined} TTL in seconds
*/
function computeTTL (expiry) {
if (expiry === undefined || expiry === null) return undefined
if (expiry instanceof Date) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

computeTTL can return a negative TTL if the provided Date is in the past. Callers will likely get unexpected behavior (e.g., negative cache TTLs). Consider returning 0 or throwing an error for expired dates.

Suggested change
if (expiry instanceof Date) {
function computeTTL (expiry) {
if (expiry === undefined || expiry === null) return undefined
if (expiry instanceof Date) {
const ttl = Math.floor((expiry.getTime() - Date.now()) / 1000)
if (ttl < 0) throw new Error('expiry date is in the past')
return ttl
}
if (typeof expiry !== 'number' || expiry < 0) throw new Error('expiry must be a non-negative number of seconds')
return expiry
}

return Math.floor((expiry.getTime() - Date.now()) / 1000)
}
return expiry
}

/**
* Truncates a value to the max allowed byte size for state storage.
*
* @private
* @param {string} value the value to sanitize
* @param {number} maxBytes max allowed size in bytes
* @returns {string} the value, truncated if necessary
*/
function sanitizeValue (value, maxBytes) {
const encoded = Buffer.from(value)
if (encoded.length <= maxBytes) return value
return encoded.slice(0, maxBytes).toString()
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Buffer.from(value) defaults to UTF-8 encoding, but slicing at an arbitrary byte boundary can split a multibyte character, producing an invalid/garbled string. Use a TextDecoder or ensure truncation happens on a character boundary.

Suggested change
}
function sanitizeValue (value, maxBytes) {
const encoded = Buffer.from(value, 'utf8')
if (encoded.length <= maxBytes) return value
// Truncate safely on a character boundary by decoding with replacement
return new TextDecoder('utf-8', { fatal: false }).decode(encoded.slice(0, maxBytes)).replace(/\uFFFD$/, '')
}


module.exports = {
withHiddenFields,
isInternalToAdobeRuntime,
formatAjvErrors
formatAjvErrors,
computeTTL,
sanitizeValue
}
Loading