8000 Merge pull request #468 from influxdata/467/sanitize_better · influxdata/influxdb-client-js@4381433 · GitHub
[go: up one dir, main page]

Skip to content

Commit 4381433

Browse files
authored
Merge pull request #468 from influxdata/467/sanitize_better
fix(core): repair sanitizing of numbers and regular expressions
2 parents a1ffdad + e6f5f7f commit 4381433

File tree

3 files changed

+85
-31
lines changed

3 files changed

+85
-31
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44

55
1. [#460](https://github.com/influxdata/influxdb-client-js/pull/460): Add type definitions for typescript 4.7+.
66

7+
### Bug Fixes
8+
9+
1. [#468](https://github.com/influxdata/influxdb-client-js/pull/468): Repair sanitizing of number and regexp values.
10+
711
### Other
812

913
1. [#462](https://github.com/influxdata/influxdb-client-js/pull/462): Upgrade to typescript 4.7.

packages/core/src/query/flux.ts

Lines changed: 56 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -112,24 +112,26 @@ export function fluxString(value: any): FluxParameterLike {
112112
* @throws Error if the the value cannot be sanitized
113113
*/
114114
export function sanitizeFloat(value: any): string {
115-
if (typeof value === 'number') {
116-
if (!isFinite(value)) {
117-
throw new Error(`not a flux float: ${value}`)
115+
const val = Number(value)
116+
if (!isFinite(val)) {
117+
if (typeof value === 'number') {
118+
return `float(v: "${val}")`
118119
}
119-
return value.toString()
120+
throw new Error(`not a flux float: ${value}`)
120121
}
121-
const val = String(value)
122-
let dot = false
123-
for (const c of val) {
122+
// try to return a flux float literal if possible
123+
// https://docs.influxdata.com/flux/v0.x/data-types/basic/float/#float-syntax
124+
const strVal = val.toString()
125+
let hasDot = false
126+
for (const c of strVal) {
127+
if ((c >= '0' && c <= '9') || c == '-') continue
124128
if (c === '.') {
125-
if (dot) throw new Error(`not a flux float: ${val}`)
126-
dot = !dot
129+
hasDot = true
127130
continue
128131
}
129-
if (c !== '.' && c !== '-' && (c < '0' || c > '9'))
130-
throw new Error(`not a flux float: ${val}`)
132+
return `float(v: "${strVal}")`
131133
}
132-
return val
134+
return hasDot ? strVal : strVal + '.0'
133135
}
134136
/**
135137
* Creates a flux float literal.
@@ -139,16 +141,41 @@ export function fluxFloat(value: any): FluxParameterLike {
139141
}
140142

141143
/**
142-
* Creates a flux integer literal.
144+
* Sanitizes integer value to avoid injections.
145+
* @param value - InfluxDB integer literal
146+
* @returns sanitized integer value
147+
* @throws Error if the the value cannot be sanitized
143148
*/
144-
export function fluxInteger(value: any): FluxParameterLike {
145-
const val = sanitizeFloat(value)
149+
export function sanitizeInteger(value: any): string {
150+
// https://docs.influxdata.com/flux/v0.x/data-types/basic/int/
151+
// Min value: -9223372036854775808
152+
// Max value: 9223372036854775807
153+
// "9223372036854775807".length === 19
154+
const strVal = String(value)
155+
const negative = strVal.startsWith('-')
156+
const val = negative ? strVal.substring(1) : strVal
157+
if (val.length === 0 || val.length > 19) {
158+
throw new Error(`not a flux integer: ${strVal}`)
159+
}
146160
for (const c of val) {
147-
if (c === '.') {
148-
throw new Error(`not a flux integer: ${val}`)
161+
if (c < '0' || c > '9') throw new Error(`not a flux integer: ${strVal}`)
162+
}
163+
if (val.length === 19) {
164+
if (negative && val > '9223372036854775808') {
165+
throw new Error(`flux integer out of bounds: ${strVal}`)
166+
}
167+
if (!negative && val > '9223372036854775807') {
168+
throw new Error(`flux integer out of bounds: ${strVal}`)
149169
}
150170
}
151-
return new FluxParameter(val)
171+
return strVal
172+
}
173+
174+
/**
175+
* Creates a flux integer literal.
176+
*/
177+
export function fluxInteger(value: any): FluxParameterLike {
178+
return new FluxParameter(sanitizeInteger(value))
152179
}
153180

154181
function sanitizeDateTime(value: any): string {
@@ -170,14 +197,19 @@ export function fluxDuration(value: any): FluxParameterLike {
170197
}
171198

172199
function sanitizeRegExp(value: any): string {
173-
return `regexp.compile(v: "${sanitizeString(value)}")`
200+
if (value instanceof RegExp) {
201+
return value.toString()
202+
}
203+
return new RegExp(value).toString()
174204
}
175205

176206
/**
177-
* Creates flux regexp literal.
207+
* Creates flux regexp literal out of a regular expression. See
208+
* https://docs.influxdata.com/flux/v0.x/data-types/basic/regexp/#regular-expression-syntax
209+
* for details.
178210
*/
179211
export function fluxRegExp(value: any): FluxParameterLike {
180-
// let the server decide if it can be parsed
212+
// let the server decide if a regexp can be parsed
181213
return new FluxParameter(sanitizeRegExp(value))
182214
}
183215

@@ -216,6 +248,9 @@ export function toFluxValue(value: any): string {
216248
} else if (typeof value === 'string') {
217249
return `"${sanitizeString(value)}"`
218250
} else if (typeof value === 'number') {
251+
if (Number.isSafeInteger(value)) {
252+
return sanitizeInteger(value)
253+
}
219254
return sanitizeFloat(value)
220255
} else if (typeof value === 'object') {
221256
if (typeof value[FLUX_VALUE] === 'function') {

packages/core/test/unit/query/flux.test.ts

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ describe('Flux Values', () => {
3131
expect(() => fluxInteger(NaN)).to.throw()
3232
expect(() => fluxInteger(Infinity)).to.throw()
3333
expect(() => fluxInteger(-Infinity)).to.throw()
34+
expect(() => fluxInteger('')).to.throw()
35+
expect(fluxInteger('-9223372036854775808').toString()).equals(
36+
'-9223372036854775808'
37+
)
38+
expect(() => fluxInteger('-9223372036854775809').toString()).throws()
39+
expect(fluxInteger('9223372036854775807').toString()).equals(
40+
'9223372036854775807'
41+
)
42+
expect(() => fluxInteger('9223372036854775808').toString()).throws()
3443
})
3544
it('creates fluxBool', () => {
3645
expect(fluxBool('true').toString()).equals('true')
@@ -50,12 +59,19 @@ describe('Flux Values', () => {
5059
const subject = fluxFloat(123.456)
5160
expect(subject.toString()).equals('123.456')
5261
expect((subject as any)[FLUX_VALUE]()).equals('123.456')
53-
expect(fluxFloat('-123').toString()).equals('-123')
62+
expect(fluxFloat('-123').toString()).equals('-123.0')
63+
expect(fluxFloat(1e20).toString()).equals('100000000000000000000.0')
64+
expect(fluxFloat(1e-2).toString()).equals('0.01')
65+
expect(fluxFloat(1e21).toString()).equals('float(v: "1e+21")')
66+
expect(fluxFloat(1e-21).toString()).equals('float(v: "1e-21")')
67+
expect(fluxFloat(Infinity).toString()).equals('float(v: "Infinity")')
68+
expect(fluxFloat(-Infinity).toString()).equals('float(v: "-Infinity")')
69+
expect(fluxFloat(NaN).toString()).equals('float(v: "NaN")')
5470
expect(() => fluxFloat('123..')).to.throw()
5571
expect(() => fluxFloat('123.a')).to.throw()
56-
expect(() => fluxFloat(NaN)).to.throw()
57-
expect(() => fluxFloat(Infinity)).to.throw()
58-
expect(() => fluxFloat(-Infinity)).to.throw()
72+
expect(() => fluxFloat({})).to.throw()
73+
expect(() => fluxFloat(undefined)).to.throw()
74+
expect(fluxFloat({toString: () => '1'}).toString()).equals('1.0')
5975
})
6076
it('creates fluxDuration', () => {
6177
const subject = fluxDuration('1ms')
@@ -70,10 +86,8 @@ describe('Flux Values', () => {
7086
expect((subject as any)[FLUX_VALUE]()).equals(fluxValue)
7187
})
7288
it('creates fluxRegExp', () => {
73-
const subject = fluxRegExp('/abc/')
74-
const fluxValue = 'regexp.compile(v: "/abc/")'
75-
expect(subject.toString()).equals(fluxValue)
76-
expect((subject as any)[FLUX_VALUE]()).equals(fluxValue)
89+
expect(fluxRegExp('abc').toString()).equals('/abc/')
90+
expect(fluxRegExp(/abc/i).toString()).equals('/abc/i')
7791
})
7892
it('creates fluxString', () => {
7993
const subject = fluxString('abc')
@@ -92,9 +106,10 @@ describe('Flux Values', () => {
92106
{value: 1, flux: '1'},
93107
{value: 1.1, flux: '1.1'},
94108
{value: -1.1, flux: '-1.1'},
109+
{value: -1e-21, flux: 'float(v: "-1e-21")'},
95110
{value: 'a', flux: '"a"'},
96111
{value: new Date(1589521447471), flux: '2020-05-15T05:44:07.471Z'},
97-
{value: /abc/, flux: 'regexp.compile(v: "/abc/")'},
112+
{value: /abc/, flux: '/abc/'},
98113
{
99114
value: {
100115
toString: function (): string {
@@ -199,7 +214,7 @@ describe('Flux Tagged Template', () => {
199214
value: flux`${new Date(1589521447471)}`,
200215
flux: '2020-05-15T05:44:07.471Z',
201216
},
202-
{value: flux`${/abc/}`, flux: 'regexp.compile(v: "/abc/")'},
217+
{value: flux`${/abc/}`, flux: '/abc/'},
203218
{
204219
value: flux`${{
205220
toString: function (): string {

0 commit comments

Comments
 (0)
0