Skip to content

Commit

Permalink
Avoid invoking potentially unbounded computation in object toString m…
Browse files Browse the repository at this point in the history
…ethods
  • Loading branch information
szegedi committed Jan 6, 2025
1 parent 893c27c commit 5b089cb
Showing 1 changed file with 101 additions and 1 deletion.
102 changes: 101 additions & 1 deletion packages/dd-trace/src/profiling/profilers/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,23 @@ const pprofValueUnit = 'nanoseconds'
const dateOffset = BigInt(Math.round(performance.timeOrigin * MS_TO_NS))

function labelFromStr (stringTable, key, valStr) {
return new Label({ key, str: stringTable.dedup(String(valStr)) })
return new Label({ key, str: stringTable.dedup(safeToString(valStr)) })
}

// We don't want to invoke toString for objects and functions, rather we'll
// provide dummy values. These values are not meant to emulate built-in toString
// behavior.
function safeToString (val) {
switch (typeof val) {
case 'string':
return val
case 'object':
return '[object]'
case 'function':
return '[function]'
default:
return String(val)
}
}

function labelFromStrStr (stringTable, keyStr, valStr) {
Expand Down Expand Up @@ -153,10 +169,94 @@ class FilesystemDecorator {
}
}

class CryptoDecorator {
constructor (stringTable) {
this.stringTable = stringTable
this.operationKey = stringTable.dedup('operation')
this.typeKey = stringTable.dedup('type')
this.sizeKey = stringTable.dedup('size')
this.digestKey = stringTable.dedup('digest')
this.keyLenKey = stringTable.dedup('keylen')
this.iterationsKey = stringTable.dedup('iterations')
this.offsetKey = stringTable.dedup('offset')
this.minKey = stringTable.dedup('min')
this.maxKey = stringTable.dedup('max')
this.algorithmKey = stringTable.dedup('algorithm')
}

decorateSample (sampleInput, item) {
const labels = sampleInput.label
const stringTable = this.stringTable
const detail = item.detail
const operation = detail.operation

function pushDetailStr (key, index) {
labels.push(labelFromStrStr(stringTable, key, detail.args[index]))
}

function pushDetailNum (key, index) {
labels.push(new Label({ key, num: detail.args[index] }))
}

labels.push(labelFromStr(stringTable, this.operationKey, operation))
switch (operation) {
case 'checkPrime':
break
case 'generateKey':
pushDetailStr(this.typeKey, 0)
break
case 'generateKeyPair':
pushDetailStr(this.typeKey, 0)
break
case 'generatePrime':
pushDetailNum(this.sizeKey, 0)
break
case 'hkdf':
pushDetailStr(this.digestKey, 0)
pushDetailNum(this.keyLenKey, 4)
break
case 'pbkdf2':
pushDetailNum(this.iterationsKey, 2)
pushDetailNum(this.keyLenKey, 3)
pushDetailStr(this.digestKey, 4)
break
case 'randomBytes':
pushDetailNum(this.sizeKey, 0)
break
case 'randomFill':
if (typeof detail.args[1] === 'number') {
pushDetailNum(this.offsetKey, 1)
if (typeof detail.args[2] === 'number') {
pushDetailNum(this.sizeKey, 2)
}
}
break
case 'randomInt':
if (typeof detail.args[0] === 'number') {
if (typeof detail.args[0] === 'number') {
pushDetailNum(this.minKey, 0)
pushDetailNum(this.maxKey, 1)
} else {
pushDetailNum(this.maxKey, 0)
}
}
break
case 'scrypt':
pushDetailNum(this.keyLenKey, 2)
break
case 'sign':
case 'verify':
pushDetailStr(this.algorithmKey, 0)
break
}
}
}

// Keys correspond to PerformanceEntry.entryType, values are constructor
// functions for type-specific decorators.
const decoratorTypes = {
fs: FilesystemDecorator,
crypto: CryptoDecorator,
dns: DNSDecorator,
gc: GCDecorator,
net: NetDecorator
Expand Down

0 comments on commit 5b089cb

Please sign in to comment.