Skip to content

Commit

Permalink
Rollback incorrect and unsecure "Accept empty object for optional jso…
Browse files Browse the repository at this point in the history
…n values"
  • Loading branch information
plokhotnyuk committed Jan 10, 2025
1 parent 4b6228a commit 483658b
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import scala.util.control.NonFatal

import zio.json.JsonDecoder.{ JsonError, UnsafeJson }
import zio.json.ast.Json
import zio.json.internal.{ Lexer, RecordingReader, RetractReader, StringMatrix, WithRecordingReader, Write }
import zio.json.internal.{ Lexer, RecordingReader, RetractReader, StringMatrix, Write }
import zio.json.{
JsonCodec => ZJsonCodec,
JsonDecoder => ZJsonDecoder,
Expand Down Expand Up @@ -649,33 +649,15 @@ object JsonCodec {
case _: ZJsonDecoder[_] =>
}

private val emptyObjectDecoder: ZJsonDecoder[Boolean] =
(_: List[JsonError], in: RetractReader) => {
val c1 = in.nextNonWhitespace()
val c2 = in.nextNonWhitespace()
c1 == '{' && c2 == '}'
}

private[schema] def option[A](A: ZJsonDecoder[A]): ZJsonDecoder[Option[A]] =
new ZJsonDecoder[Option[A]] { self =>

new ZJsonDecoder[Option[A]] {
private[this] val ull: Array[Char] = "ull".toCharArray

def unsafeDecode(trace: List[JsonError], in: RetractReader): Option[A] =
(in.nextNonWhitespace(): @switch) match {
case 'n' =>
Lexer.readChars(trace, in, ull, "null")
None
case '{' =>
// If we encounter a `{` it could either be a legitimate object or an empty object marker
in.retract()
val rr = new WithRecordingReader(in, 2)
if (emptyObjectDecoder.unsafeDecode(trace, rr)) {
None
} else {
rr.rewind()
Some(A.unsafeDecode(trace, rr))
}
case _ =>
in.retract()
Some(A.unsafeDecode(trace, in))
Expand Down Expand Up @@ -1101,13 +1083,13 @@ object JsonCodec {
case BadEnd() => ()
case _: UnsafeJson =>
in.retract()
val in2 = new zio.json.internal.WithRecordingReader(in, 64)
val rr = RecordingReader(in)
try {
left = Some(leftDecoder.unsafeDecode(trace, in2))
left = Some(leftDecoder.unsafeDecode(trace, rr))
} catch {
case UnsafeJson(_) =>
in2.rewind()
right = Some(rightDecoder.unsafeDecode(trace, in2))
rr.rewind()
right = Some(rightDecoder.unsafeDecode(trace, rr))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -997,20 +997,6 @@ object JsonCodecSpec extends ZIOSpecDefault {
charSequenceToByteChunk("""{"a":"s"}""")
)
},
test("case class with option fields accept empty json object as value") {
assertDecodes(
WithOptionFields.schema,
WithOptionFields(Some("s"), None),
charSequenceToByteChunk("""{"a":"s", "b":{}}""")
)
},
test("case class with complex option field accept empty json object as value") {
assertDecodes(
WithComplexOptionField.schema,
WithComplexOptionField(None),
charSequenceToByteChunk("""{"order":{}}""")
)
},
test("case class with complex option field correctly decodes") {
assertDecodes(
WithComplexOptionField.schema,
Expand Down

0 comments on commit 483658b

Please sign in to comment.