Skip to content

Commit d596d32

Browse files
committed
fix(decoder): decode list should use correct index
Always use zero will get an reversed list...
1 parent e51b5c8 commit d596d32

File tree

1 file changed

+70
-53
lines changed

1 file changed

+70
-53
lines changed

src/commonMain/kotlin/space/iseki/bencoding/BencodeDecoder0.kt

Lines changed: 70 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ internal class BencodeDecoder0(
2929
return f()
3030
}
3131

32-
private val m = M(lexer)
32+
private val m = M()
3333
override fun decodeBooleanElement(descriptor: SerialDescriptor, index: Int): Boolean =
3434
unsupported(descriptor, index)
3535

@@ -102,44 +102,67 @@ internal class BencodeDecoder0(
102102

103103
override fun decodeByteArray(): ByteArray = lexer.nextBytes()
104104

105-
@OptIn(ExperimentalSerializationApi::class)
106-
private class M(val lexer: Lexer) {
105+
companion object {
106+
// Base constants used for bit shifting
107+
private const val C_READ = 1
108+
private const val T_LIST = 1 shl 1
109+
private const val T_MAP_KEY = 1 shl 2
110+
private const val T_MAP_VAL = 1 shl 3
111+
private const val T_OBJ = 1 shl 4
107112

108-
companion object {
109-
// Base constants used for bit shifting
110-
private const val C_READ = 1
111-
private const val T_LIST = 1 shl 1
112-
private const val T_MAP_KEY = 1 shl 2
113-
private const val T_MAP_VAL = 1 shl 3
114-
private const val T_OBJ = 1 shl 4
115-
private const val C_NEG = 1 shl 31
113+
// LIST related constants
114+
const val LIST_IDLE = T_LIST
115+
const val LIST_READ = T_LIST or C_READ
116116

117-
// LIST related constants
118-
const val LIST_IDLE = C_NEG or T_LIST
119-
const val LIST_READ = C_NEG or T_LIST or C_READ
117+
// MAP_KEY related constants
118+
const val MAP_KEY_IDLE = T_MAP_KEY
119+
const val MAP_KEY_READ = T_MAP_KEY or C_READ
120120

121-
// MAP_KEY related constants
122-
const val MAP_KEY_IDLE = C_NEG or T_MAP_KEY
123-
const val MAP_KEY_READ = C_NEG or T_MAP_KEY or C_READ
121+
// MAP_VAL related constants
122+
const val MAP_VAL_IDLE = T_MAP_VAL
123+
const val MAP_VAL_READ = T_MAP_VAL or C_READ
124124

125-
// MAP_VAL related constants
126-
const val MAP_VAL_IDLE = C_NEG or T_MAP_VAL
127-
const val MAP_VAL_READ = C_NEG or T_MAP_VAL or C_READ
125+
// OBJ related constants
126+
const val OBJ_IDLE = T_OBJ
127+
const val OBJ_READ = T_OBJ or C_READ
128128

129-
// OBJ related constants
130-
const val OBJ_IDLE = C_NEG or T_OBJ
129+
}
131130

132-
}
133131

134-
// when OBJ_READ, the stack top is the decoded element index
135-
private var stack = IntArray(0)
132+
@OptIn(ExperimentalSerializationApi::class)
133+
private inner class M {
134+
135+
private var stack = LongArray(0)
136136
private var sp = -1
137137
private fun ensureMoreSpace() {
138138
if (sp + 1 == stack.size) {
139-
stack = stack.copyInto(IntArray(stack.size.coerceAtLeast(2) * 2))
139+
stack = stack.copyInto(LongArray(stack.size.coerceAtLeast(2) * 2))
140140
}
141141
}
142142

143+
private fun currIndex(): Int {
144+
val s = stack[sp]
145+
return s.toInt()
146+
}
147+
148+
private fun currState(): Int {
149+
val s = stack[sp]
150+
return (s ushr 32).toInt()
151+
}
152+
153+
private fun setIndex(index: Int) {
154+
stack[sp] = index.toLong() and 0xFFFFFFFFL or (stack[sp] and (0xffffffffL shl 32))
155+
}
156+
157+
private fun setState(state: Int) {
158+
stack[sp] = (state.toLong() shl 32) or (stack[sp] and 0xFFFFFFFFL)
159+
}
160+
161+
private fun pushState(state: Int) {
162+
ensureMoreSpace()
163+
stack[++sp] = state.toLong() shl 32
164+
}
165+
143166
private fun laExpect(t: Int) {
144167
if (t != lexer.la()) {
145168
val exp = Lexer.name(t)
@@ -161,27 +184,24 @@ internal class BencodeDecoder0(
161184
}
162185

163186
fun begin(d: SerialDescriptor) {
164-
ensureMoreSpace()
165187
when (val kind = d.kind) {
166188
StructureKind.LIST -> {
167189
consumeExpect(Lexer.LIST)
168-
stack[++sp] = LIST_IDLE
190+
pushState(LIST_IDLE)
191+
setIndex(-1)
169192
}
170193

171194
StructureKind.MAP -> {
172195
consumeExpect(Lexer.DICT)
173-
stack[++sp] = MAP_KEY_IDLE
196+
pushState(MAP_KEY_IDLE)
174197
}
175198

176199
StructureKind.CLASS, StructureKind.OBJECT -> {
177200
consumeExpect(Lexer.DICT)
178-
stack[++sp] = OBJ_IDLE
201+
pushState(OBJ_IDLE)
179202
}
180203

181-
else -> throw BencodeDecodeException(
182-
lexer.pos(),
183-
"unsupported structured descriptor: ${d.serialName}, kind: $kind"
184-
)
204+
else -> reportError("unsupported structured descriptor: ${d.serialName}, kind: $kind")
185205
}
186206
}
187207

@@ -195,16 +215,9 @@ internal class BencodeDecoder0(
195215
}
196216

197217
fun g(sd: SerialDescriptor, i: Int) {
198-
val s = stack[sp]
199-
if (s >= 0) {
200-
check(s == i) { "bad index: $i, expect: $s" }
201-
stack[sp] = OBJ_IDLE
202-
} else {
203-
if (s and C_READ == 0) {
204-
error("call decodeElementIndex before decode*")
205-
}
206-
stack[sp] = postReadStateOf(stack[sp])
207-
}
218+
if (currState() and C_READ == 0) reportError("not in read state", sd, i)
219+
if (currIndex() != i) reportError("bad index: $i, expect: ${currIndex()}", sd, i)
220+
setState(postReadStateOf(currState()))
208221
}
209222

210223
private fun postReadStateOf(old: Int): Int {
@@ -217,17 +230,18 @@ internal class BencodeDecoder0(
217230
}
218231

219232
private fun goAround(sd: SerialDescriptor, state: Int): Int {
220-
stack[sp] = state
233+
setState(state)
221234
return d(sd)
222235
}
223236

224237
fun d(sd: SerialDescriptor): Int {
225-
when (val s = stack[sp]) {
238+
when (val s = currState()) {
226239
LIST_IDLE -> {
227240
if (lexer.la() == Lexer.END) return CompositeDecoder.DECODE_DONE
228241
laUnexpect(Lexer.EOF)
229-
stack[sp] = LIST_READ
230-
return 0
242+
setState(LIST_READ)
243+
setIndex(currIndex() + 1)
244+
return currIndex()
231245
}
232246

233247
LIST_READ -> {
@@ -238,8 +252,9 @@ internal class BencodeDecoder0(
238252
MAP_KEY_IDLE -> {
239253
if (lexer.la() == Lexer.END) return CompositeDecoder.DECODE_DONE
240254
laExpect(Lexer.STRING)
241-
stack[sp] = MAP_KEY_READ
242-
return 0
255+
setState(MAP_KEY_READ)
256+
setIndex(currIndex() + 1)
257+
return currIndex()
243258
}
244259

245260
MAP_KEY_READ -> {
@@ -251,8 +266,9 @@ internal class BencodeDecoder0(
251266
MAP_VAL_IDLE -> {
252267
laUnexpect(Lexer.END)
253268
laUnexpect(Lexer.EOF)
254-
stack[sp] = MAP_VAL_READ
255-
return 1
269+
setState(MAP_VAL_READ)
270+
setIndex(currIndex() + 1)
271+
return currIndex()
256272
}
257273

258274
MAP_VAL_READ -> {
@@ -269,7 +285,8 @@ internal class BencodeDecoder0(
269285
lexer.skipValue()
270286
continue
271287
}
272-
stack[sp] = index
288+
setIndex(index)
289+
setState(OBJ_READ)
273290
return index
274291
}
275292
}

0 commit comments

Comments
 (0)