Skip to content

Commit 4536dca

Browse files
authored
Fix unsafe object lookups (#99)
* Fix unsafe object lookups * fix warn order * js objects keys are stringified * use hasOwnProperty instead of searching keys * hasOwnProperty -> Object.hasOwn
1 parent 494315f commit 4536dca

File tree

1 file changed

+19
-18
lines changed

1 file changed

+19
-18
lines changed

index.js

+19-18
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
const mojangson = require('mojangson')
22
const vsprintf = require('./format')
3+
const debug = require('debug')('minecraft-protocol')
34

45
module.exports = loader
6+
const getValueSafely = (obj, key, def) => Object.hasOwn(obj, key) ? obj[key] : def
57

68
function loader (registryOrVersion) {
79
const registry = typeof registryOrVersion === 'string' ? require('prismarine-registry')(registryOrVersion) : registryOrVersion
@@ -76,6 +78,7 @@ function loader (registryOrVersion) {
7678
} else {
7779
throw new Error('Expected String or Object for Message argument')
7880
}
81+
this.warn = displayWarning ? console.warn : debug
7982
this.parse(displayWarning)
8083
}
8184

@@ -84,7 +87,7 @@ function loader (registryOrVersion) {
8487
* Called by the Constructor
8588
* @return {void}
8689
*/
87-
parse (displayWarning = false) {
90+
parse () {
8891
const json = this.json
8992
// Message scope for callback functions
9093
// There is EITHER, a text property or a translate property
@@ -183,19 +186,18 @@ function loader (registryOrVersion) {
183186
break
184187
}
185188
// Make sure color is valid
186-
if (Array.prototype.indexOf && this.color &&
187-
supportedColors.indexOf(this.color) === -1 &&
188-
!this.color.match(/#[a-fA-F\d]{6}/) && displayWarning) {
189-
console.warn('ChatMessage parsed with unsupported color', this.color)
189+
if (this.color && !supportedColors.includes(this.color) && !this.color.match(/#[a-fA-F\d]{6}/)) {
190+
this.warn('ChatMessage parsed with unsupported color', this.color)
191+
this.color = null
190192
}
191193

192194
// Parse click event
193195
if (typeof json.clickEvent === 'object') {
194196
this.clickEvent = json.clickEvent
195197
if (typeof this.clickEvent.action !== 'string') {
196198
throw new Error('ClickEvent action missing in ChatMessage')
197-
} else if (Array.prototype.indexOf && supportedClick.indexOf(this.clickEvent.action) === -1 && displayWarning) {
198-
console.warn('ChatMessage parsed with unsupported clickEvent', this.clickEvent.action)
199+
} else if (!supportedClick.includes(this.clickEvent.action)) {
200+
this.warn('ChatMessage parsed with unsupported clickEvent', this.clickEvent.action)
199201
}
200202
}
201203

@@ -204,8 +206,8 @@ function loader (registryOrVersion) {
204206
this.hoverEvent = json.hoverEvent
205207
if (typeof this.hoverEvent.action !== 'string') {
206208
throw new Error('HoverEvent action missing in ChatMessage')
207-
} else if (Array.prototype.indexOf && supportedHover.indexOf(this.hoverEvent.action) === -1 && displayWarning) {
208-
console.warn('ChatMessage parsed with unsupported hoverEvent', this.hoverEvent.action)
209+
} else if (!supportedHover.includes(this.hoverEvent.action)) {
210+
this.warn('ChatMessage parsed with unsupported hoverEvent', this.hoverEvent.action)
209211
}
210212
// Special case
211213
if (this.hoverEvent.action === 'show_item') {
@@ -226,7 +228,7 @@ function loader (registryOrVersion) {
226228
try {
227229
this.hoverEvent.value = mojangson.parse(content)
228230
} catch (err) {
229-
231+
debug(err)
230232
}
231233
}
232234
}
@@ -302,8 +304,7 @@ function loader (registryOrVersion) {
302304
const _with = this.with ?? []
303305

304306
const args = _with.map(entry => entry.toString(lang))
305-
const format = lang[this.translate] ?? this.translate
306-
307+
const format = getValueSafely(lang, this.translate, this.translate)
307308
message += vsprintf(format, args)
308309
}
309310
if (this.extra) {
@@ -355,16 +356,15 @@ function loader (registryOrVersion) {
355356
return codes[code]
356357
}).join('')
357358

358-
if ((typeof this.text === 'string' || typeof this.text === 'number')/* && this.text !== '' */) message += this.text
359+
if ((typeof this.text === 'string') || (typeof this.text === 'number')) message += this.text
359360
else if (this.translate !== undefined) {
360361
const _with = this.with ?? []
361362

362363
const args = _with.map(entry => {
363364
const entryAsMotd = entry.toMotd(lang, this)
364365
return entryAsMotd + (entryAsMotd.includes('§') ? '§r' + message : '')
365366
})
366-
const format = lang[this.translate] ?? this.translate
367-
367+
const format = getValueSafely(lang, this.translate, this.translate)
368368
message += vsprintf(format, args)
369369
}
370370
if (this.extra) {
@@ -416,7 +416,7 @@ function loader (registryOrVersion) {
416416
params.push(param.toHTML(lang, styles, allowedFormats))
417417
}
418418
}
419-
const format = lang[this.translate] ?? this.translate
419+
const format = getValueSafely(lang, this.translate, this.translate)
420420
str += vsprintf(escapeHtml(format), params)
421421
}
422422

@@ -442,8 +442,9 @@ function loader (registryOrVersion) {
442442
// For example,
443443
// printf("<%s> %s" /* fmt string */, [sender], [content])
444444
static fromNetwork (type, params) {
445-
const format = registry.chatFormattingById[type]
446-
return new ChatMessage({ translate: format.formatString, with: format.parameters.map(p => params[p]) })
445+
const format = getValueSafely(registry.chatFormattingById, type)
446+
if (format == null) throw new Error('unknown chat format code: ' + type) // The server may be attempting to send a chat message before sending a login codec, which is not allowed
447+
return new ChatMessage({ translate: format.formatString, with: format.parameters.map(p => getValueSafely(params, p, '')) })
447448
}
448449
}
449450

0 commit comments

Comments
 (0)