Skip to content

Commit 1fd65da

Browse files
authored
Merge pull request #469 from gnieh/stack-overflow-nested
Fix stack overflow when diffing wide objects
2 parents f19d200 + 9e7f431 commit 1fd65da

File tree

7 files changed

+94
-16
lines changed

7 files changed

+94
-16
lines changed

.github/workflows/ci.yml

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ concurrency:
2424

2525
jobs:
2626
build:
27-
name: Build and Test
27+
name: Test
2828
strategy:
2929
matrix:
30-
os: [ubuntu-latest]
30+
os: [ubuntu-22.04]
3131
scala: [2.12, 2.13, 3]
3232
java: [temurin@11]
3333
project: [diffsonJVM, diffsonJS, diffsonNative]
@@ -39,6 +39,9 @@ jobs:
3939
with:
4040
fetch-depth: 0
4141

42+
- name: Setup sbt
43+
uses: sbt/setup-sbt@v1
44+
4245
- name: Setup Java (temurin@11)
4346
id: setup-java-temurin-11
4447
if: matrix.java == 'temurin@11'
@@ -56,7 +59,7 @@ jobs:
5659
run: sbt githubWorkflowCheck
5760

5861
- name: Check headers and formatting
59-
if: matrix.java == 'temurin@11' && matrix.os == 'ubuntu-latest'
62+
if: matrix.java == 'temurin@11' && matrix.os == 'ubuntu-22.04'
6063
run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' headerCheckAll scalafmtCheckAll 'project /' scalafmtSbtCheck
6164

6265
- name: scalaJSLink
@@ -71,11 +74,11 @@ jobs:
7174
run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' test
7275

7376
- name: Check binary compatibility
74-
if: matrix.java == 'temurin@11' && matrix.os == 'ubuntu-latest'
77+
if: matrix.java == 'temurin@11' && matrix.os == 'ubuntu-22.04'
7578
run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' mimaReportBinaryIssues
7679

7780
- name: Generate API documentation
78-
if: matrix.java == 'temurin@11' && matrix.os == 'ubuntu-latest'
81+
if: matrix.java == 'temurin@11' && matrix.os == 'ubuntu-22.04'
7982
run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' doc
8083

8184
- name: Make target directories
@@ -99,7 +102,7 @@ jobs:
99102
if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main')
100103
strategy:
101104
matrix:
102-
os: [ubuntu-latest]
105+
os: [ubuntu-22.04]
103106
java: [temurin@11]
104107
runs-on: ${{ matrix.os }}
105108
steps:
@@ -108,6 +111,9 @@ jobs:
108111
with:
109112
fetch-depth: 0
110113

114+
- name: Setup sbt
115+
uses: sbt/setup-sbt@v1
116+
111117
- name: Setup Java (temurin@11)
112118
id: setup-java-temurin-11
113119
if: matrix.java == 'temurin@11'
@@ -237,10 +243,10 @@ jobs:
237243

238244
dependency-submission:
239245
name: Submit Dependencies
240-
if: github.event_name != 'pull_request'
246+
if: github.event.repository.fork == false && github.event_name != 'pull_request'
241247
strategy:
242248
matrix:
243-
os: [ubuntu-latest]
249+
os: [ubuntu-22.04]
244250
java: [temurin@11]
245251
runs-on: ${{ matrix.os }}
246252
steps:
@@ -249,6 +255,9 @@ jobs:
249255
with:
250256
fetch-depth: 0
251257

258+
- name: Setup sbt
259+
uses: sbt/setup-sbt@v1
260+
252261
- name: Setup Java (temurin@11)
253262
id: setup-java-temurin-11
254263
if: matrix.java == 'temurin@11'
@@ -272,7 +281,7 @@ jobs:
272281
name: Validate Steward Config
273282
strategy:
274283
matrix:
275-
os: [ubuntu-latest]
284+
os: [ubuntu-22.04]
276285
java: [temurin@11]
277286
runs-on: ${{ matrix.os }}
278287
steps:

build.sbt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import com.typesafe.tools.mima.core._
22

33
val scala212 = "2.12.19"
4-
val scala213 = "2.13.12"
4+
val scala213 = "2.13.13"
55
val scala3 = "3.3.3"
66

77
val scalatestVersion = "3.2.18"
@@ -13,7 +13,7 @@ ThisBuild / crossScalaVersions := Seq(elems = scala212, scala213, scala3)
1313

1414
ThisBuild / tlFatalWarnings := false
1515

16-
ThisBuild / tlBaseVersion := "4.5"
16+
ThisBuild / tlBaseVersion := "4.6"
1717

1818
ThisBuild / organization := "org.gnieh"
1919
ThisBuild / organizationName := "Diffson Project"
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Copyright 2024 Diffson Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package diffson.circe
18+
19+
import diffson.jsonpatch.TestObjectDiff
20+
import io.circe.Json
21+
22+
class CirceTestObjectDiff extends TestObjectDiff[Json]

core/src/main/scala/diffson/jsonpatch/JsonDiff.scala

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,14 @@ class JsonDiff[Json](diffArray: Boolean, rememberOld: Boolean)(implicit J: Jsony
4848
case (fld, value1) :: fields1 =>
4949
fields2.get(fld) match {
5050
case Some(value2) =>
51-
fieldsDiff(fields1, fields2 - fld, path).flatMap(d => diff(value1, value2, path / fld).map(_ ++ d))
51+
Eval
52+
.defer(fieldsDiff(fields1, fields2 - fld, path))
53+
.flatMap(d => diff(value1, value2, path / fld).map(_ ++ d))
5254
case None =>
5355
// field is not in the second object, delete it
54-
fieldsDiff(fields1, fields2, path).map(
55-
_.prepend(Remove(path / fld, if (rememberOld) Some(value1) else None)))
56+
Eval
57+
.defer(fieldsDiff(fields1, fields2, path))
58+
.map(_.prepend(Remove(path / fld, if (rememberOld) Some(value1) else None)))
5659
}
5760
case Nil =>
5861
Eval.now(Chain.fromSeq(fields2.toList).map { case (fld, value) => Add(path / fld, value) })

project/build.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
sbt.version=1.9.9
1+
sbt.version=1.11.6

project/plugins.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
addSbtPlugin("org.typelevel" % "sbt-typelevel" % "0.6.7")
1+
addSbtPlugin("org.typelevel" % "sbt-typelevel" % "0.8.0")
22
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.16.0")
33
addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.17")
44
addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.7")
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2024 Diffson Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package diffson
18+
package jsonpatch
19+
20+
import org.scalatest.flatspec.AnyFlatSpec
21+
import org.scalatest.matchers.should.Matchers
22+
import diffson.jsonpatch.JsonDiff
23+
import diffson.lcs.Patience
24+
25+
abstract class TestObjectDiff[J](implicit J: Jsony[J]) extends AnyFlatSpec with Matchers {
26+
27+
implicit val lcsalg: Patience[J] = new Patience[J]
28+
29+
val diff = new JsonDiff[J](false, false)
30+
31+
"a wide object diffed with an empty one" should "not cause stack overflows" in {
32+
val json1 = J.makeObject((1 to 10000).map(i => s"key$i" -> J.Null).toMap)
33+
val json2 = J.makeObject(Map.empty)
34+
35+
diff.diff(json1, json2)
36+
}
37+
38+
"a wide object diffed with itself" should "not cause stack overflows" in {
39+
val json1 = J.makeObject((1 to 10000).map(i => s"key$i" -> J.Null).toMap)
40+
41+
diff.diff(json1, json1)
42+
}
43+
44+
}

0 commit comments

Comments
 (0)