Home [TIL] 신기한 parseInt()
Post
Cancel

[TIL] 신기한 parseInt()

문제를 풀다가 보다보니 신기해서 적어봅니다.🧐

parseInt()


parseInt는 문자열을 number 타입으로 형변환을 해줍니다. 하지만 이름에서 알 수 있듯이 소숫점은 모두 버리게 됩니다. 또한 문자열에서 숫자 이외에 알파벳이나 기호를 만나게 되면 딱 숫자까지만 파싱을 합니다. 그렇기 때문에 위의 n진수 형태의 문자열을 넣으면 다 0을 반환할 것 같지만 예외적으로 0x의 경우만 16진수로 해석하여 반환합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
parseInt("5634b") // 5634
parseInt("0.234345") // 0
parseInt("5964.23423") // 5964
parseInt("#") // NaN
parseInt("12.0123basdzsda1235467") // 12
parseInt("0.99999999999999999") // 0

// Binary
5 == "0b101" // true
parseInt("0b1") // 0

// Octal
2 == "0o2" // true
parseInt("0o2") // 0

// Hexadecimal
16 == "0x10" // true
parseInt("0x10") // 16


그렇다면 아래와 같은 경우는 어떻게 될까요?😎 각각 0.0000055를 반환합니다. 그 이유는 number 타입의 인자를 먼저 toString()을 통해서 문자열로 변환을 하는데 매우 작거나(1e-7 이하) 매우 크면(1e+21 이상) 지수 표기법(exponential notation)으로 문자열을 반환합니다. 따라서 위에서 설명했듯이 알파벳을 만나면 그 순간 파싱을 중지하기 때문에 0.00000055e-7이 되고 결국에는 5가 됩니다.

1
2
3
4
5
6
7
// parsing number type
parseInt(0.000005) // 0.000005
parseInt(0.0000005) // 5

(0.000005).toString() // "0.000005"
(0.0000005).toString() // "5e-7"
(1000000000000000000000).toString() // "1e+21"


또한 number 타입의 최대치 (9007199254740991, 2^53-1)를 넘어서면 제대로 파싱하지 못합니다. 즉, bigint 타입과 같은 매우 큰 수의 문자열을 주면 의도와는 다르게 흘러갈 수 있습니다.

1
2
3
4
5
parseInt("9007199254740991") // 9007199254740991
parseInt("9007199254740993") // 9007199254740992
parseInt("9007199254740994") // 9007199254740994
parseInt("9007199254740995") // 9007199254740996
parseInt("900719925474091233n") // 900719925474091300


Reference


[Web] Dangling markup injection

[TIL] CVE-2022-22978 : Authorization Bypass in RegexRequestMatcher

Comments powered by Disqus.