From 6e8b430d2f732cda8f1d9211fe07515810b18cb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Wed, 12 Jun 2024 13:35:23 +0200 Subject: [PATCH 1/5] Fix null pointer access when iterating over empty arrays. The PropTable.table field is a RandAA, which is a class and thus does not exhibit the more forgiving interface as built-in AAs. --- engine/source/dmdscript/iterator.d | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/engine/source/dmdscript/iterator.d b/engine/source/dmdscript/iterator.d index 515a361..5f549e3 100644 --- a/engine/source/dmdscript/iterator.d +++ b/engine/source/dmdscript/iterator.d @@ -70,7 +70,8 @@ struct Iterator ostart = o; this.o = o; this.callcontext = cc; - keys = o.proptable.table.keys.sort!((a, b) => a.compare(cc, b) < 0).release; + if (o.proptable.table) + keys = o.proptable.table.keys.sort!((a, b) => a.compare(cc, b) < 0).release; keyindex = 0; } From 7e3f12cb6b311021342b7294d88daf53e7846c4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Fri, 14 Jun 2024 20:29:19 +0200 Subject: [PATCH 2/5] Make the test suite run with Python 3. --- run-test262.sh | 10 +- test262-patches/test262-_monkeyYaml.py.patch | 13 ++ .../test262-parseTestRecord.py.patch | 13 ++ test262-patches/test262-test262.py.patch | 158 ++++++++++++++++++ 4 files changed, 190 insertions(+), 4 deletions(-) create mode 100644 test262-patches/test262-_monkeyYaml.py.patch create mode 100644 test262-patches/test262-parseTestRecord.py.patch create mode 100644 test262-patches/test262-test262.py.patch diff --git a/run-test262.sh b/run-test262.sh index 95d6866..ec945dc 100755 --- a/run-test262.sh +++ b/run-test262.sh @@ -17,18 +17,20 @@ if ! [ -d test262-harness-py ] ; then git clone https://github.com/test262-utils/test262-harness-py.git cd test262-harness-py git checkout 0f2acdd882c84cff43b9d60df7574a1901e2cdcd - cd .. echo "Applying patch to adjust the runner for the latest version of the test suite..." - sed '/self\.suite\.GetInclude("cth\.js")/d' -i test262-harness-py/src/test262.py + patch --merge -f -u -i ../test262-patches/test262-test262.py.patch -p1 + patch --merge -f -u -i ../test262-patches/test262-_monkeyYaml.py.patch -p1 + patch --merge -f -u -i ../test262-patches/test262-parseTestRecord.py.patch -p1 + cd .. fi echo "Running the test suite..." cd test262-harness-py -python2 src/test262.py --summary --non_strict_only --command ../timed-dmdscript.sh --tests=../test262 | tee ../dmdscript-test262.log | grep '=== .* failed in .* ===' +python3 src/test262.py --summary --non_strict_only --command ../timed-dmdscript.sh --tests=../test262 | tee ../dmdscript-test262.log | grep -a '=== .* failed in .* ===' cd .. EXPECTED_TO_PASS=5223 -PASSED=$(grep ' - Passed [0-9]* tests' dmdscript-test262.log | sed -n 's/.*Passed \([0-9]*\) tests.*/\1/;P') +PASSED=$(grep -a ' - Passed [0-9]* tests' dmdscript-test262.log | sed -n 's/.*Passed \([0-9]*\) tests.*/\1/;P') if [ "$PASSED" -gt "$EXPECTED_TO_PASS" ]; then echo "The number of passed tests has increased ($PASSED vs. $EXPECTED_TO_PASS)." diff --git a/test262-patches/test262-_monkeyYaml.py.patch b/test262-patches/test262-_monkeyYaml.py.patch new file mode 100644 index 0000000..0f7cdb3 --- /dev/null +++ b/test262-patches/test262-_monkeyYaml.py.patch @@ -0,0 +1,13 @@ +diff --git "a/src/_monkeyYaml.py" "b/src/_monkeyYaml.py" +index bc6d128..a8327e0 100644 +--- "a/src/_monkeyYaml.py" ++++ "b/src/_monkeyYaml.py" +@@ -75,7 +75,7 @@ def myMultilineList(lines, value): + leading = myLeadingSpaces(line) + if myIsAllSpaces(line): + pass +- elif leading < indent: ++ elif indent != None and leading < indent: + lines.insert(0, line) + break; + else: diff --git a/test262-patches/test262-parseTestRecord.py.patch b/test262-patches/test262-parseTestRecord.py.patch new file mode 100644 index 0000000..5d0281f --- /dev/null +++ b/test262-patches/test262-parseTestRecord.py.patch @@ -0,0 +1,13 @@ +diff --git "a/src/parseTestRecord.py" "b/src/parseTestRecord.py" +index 22d5664..5be3a5f 100644 +--- "a/src/parseTestRecord.py" ++++ "b/src/parseTestRecord.py" +@@ -78,7 +78,7 @@ def yamlAttrParser(testRecord, attrs, name): + parsed = yamlLoad(body) + + if (parsed is None): +- print "Failed to parse yaml in name %s"%(name) ++ print ("Failed to parse yaml in name %s"%(name)) + return + + for key in parsed: diff --git a/test262-patches/test262-test262.py.patch b/test262-patches/test262-test262.py.patch new file mode 100644 index 0000000..bc016a1 --- /dev/null +++ b/test262-patches/test262-test262.py.patch @@ -0,0 +1,158 @@ +diff --git "a/src/test262.py" "b/src/test262.py" +index c92e5bf..a6722d8 100644 +--- "a/src/test262.py" ++++ "b/src/test262.py" +@@ -42,8 +42,8 @@ def ReportError(s): + + + if not os.path.exists(EXCLUDED_FILENAME): +- print "Cannot generate (JSON) test262 tests without a file," + \ +- " %s, showing which tests have been disabled!" % EXCLUDED_FILENAME ++ print ("Cannot generate (JSON) test262 tests without a file," + \ ++ " %s, showing which tests have been disabled!" % EXCLUDED_FILENAME) + sys.exit(1) + EXCLUDE_LIST = xml.dom.minidom.parse(EXCLUDED_FILENAME) + EXCLUDE_REASON = EXCLUDE_LIST.getElementsByTagName("reason") +@@ -111,10 +111,10 @@ class TempFile(object): + text = self.text) + + def Write(self, str): +- os.write(self.fd, str) ++ os.write(self.fd, str.encode()) + + def Read(self): +- f = file(self.name) ++ f = open(self.name, "r", encoding="latin-1") + result = f.read() + f.close() + return result +@@ -128,7 +128,7 @@ class TempFile(object): + try: + self.Close() + os.unlink(self.name) +- except OSError, e: ++ except OSError as e: + logging.error("Error disposing temp file: %s", str(e)) + + +@@ -145,20 +145,20 @@ class TestResult(object): + mode = self.case.GetMode() + if self.HasUnexpectedOutcome(): + if self.case.IsNegative(): +- print "=== %s was expected to fail in %s, but didn't ===" % (name, mode) +- print "--- expected error: %s ---\n" % self.case.GetNegativeType() ++ print ("=== %s was expected to fail in %s, but didn't ===" % (name, mode)) ++ print ("--- expected error: %s ---\n" % self.case.GetNegativeType()) + else: + if long_format: +- print "=== %s failed in %s ===" % (name, mode) ++ print ("=== %s failed in %s ===" % (name, mode)) + else: +- print "%s in %s: " % (name, mode) ++ print ("%s in %s: " % (name, mode)) + self.WriteOutput(sys.stdout) + if long_format: +- print "===" ++ print ("===") + elif self.case.IsNegative(): +- print "%s failed in %s as expected" % (name, mode) ++ print ("%s failed in %s as expected" % (name, mode)) + else: +- print "%s passed in %s" % (name, mode) ++ print ("%s passed in %s" % (name, mode)) + + def WriteOutput(self, target): + out = self.stdout.strip() +@@ -302,7 +302,6 @@ class TestCase(object): + return self.test + + source = self.suite.GetInclude("sta.js") + \ +- self.suite.GetInclude("cth.js") + \ + self.suite.GetInclude("assert.js") + + if self.IsAsyncTest(): +@@ -373,7 +372,7 @@ class TestCase(object): + return result + + def Print(self): +- print self.GetSource() ++ print (self.GetSource()) + + def validate(self): + flags = self.testRecord.get("flags") +@@ -488,7 +487,7 @@ class TestSuite(object): + basename = path.basename(full_path)[:-3] + name = rel_path.split(path.sep)[:-1] + [basename] + if EXCLUDE_LIST.count(basename) >= 1: +- print 'Excluded: ' + basename ++ print ('Excluded: ' + basename) + else: + if not self.non_strict_only: + strict_case = TestCase(self, name, full_path, True) +@@ -511,9 +510,9 @@ class TestSuite(object): + def write(s): + if logfile: + self.logf.write(s + "\n") +- print s ++ print (s) + +- print ++ print () + write("=== Summary ==="); + count = progress.count + succeeded = progress.succeeded +@@ -527,12 +526,12 @@ class TestSuite(object): + positive = [c for c in progress.failed_tests if not c.case.IsNegative()] + negative = [c for c in progress.failed_tests if c.case.IsNegative()] + if len(positive) > 0: +- print ++ print () + write("Failed Tests") + for result in positive: + write(" %s in %s" % (result.case.GetName(), result.case.GetMode())) + if len(negative) > 0: +- print ++ print () + write("Expected to fail but passed ---") + for result in negative: + write(" %s in %s" % (result.case.GetName(), result.case.GetMode())) +@@ -541,7 +540,7 @@ class TestSuite(object): + for result in progress.failed_tests: + if logfile: + self.WriteLog(result) +- print ++ print () + result.ReportOutcome(False) + + def Run(self, command_template, tests, print_summary, full_summary, logname, junitfile): +@@ -585,9 +584,9 @@ class TestSuite(object): + if full_summary: + self.PrintFailureOutput(progress, logname) + else: +- print +- print "Use --full-summary to see output from failed tests" +- print ++ print () ++ print ("Use --full-summary to see output from failed tests") ++ print () + return progress.failed + + def WriteLog(self, result): +@@ -619,7 +618,7 @@ class TestSuite(object): + includes = case.GetIncludeList() + includes_dict.update(includes) + +- print includes_dict ++ print (includes_dict) + + + def Main(): +@@ -659,6 +658,6 @@ if __name__ == '__main__': + try: + code = Main() + sys.exit(code) +- except Test262Error, e: +- print "Error: %s" % e.message ++ except Test262Error as e: ++ print ("Error: %s" % e.message) + sys.exit(1) From 3f3023b913483c3e086cb7223c246b2105eee0bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Fri, 14 Jun 2024 20:30:14 +0200 Subject: [PATCH 3/5] Bump the number of passed tests up from 5223 to 5238. --- run-test262.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run-test262.sh b/run-test262.sh index ec945dc..6dfab93 100755 --- a/run-test262.sh +++ b/run-test262.sh @@ -29,7 +29,7 @@ cd test262-harness-py python3 src/test262.py --summary --non_strict_only --command ../timed-dmdscript.sh --tests=../test262 | tee ../dmdscript-test262.log | grep -a '=== .* failed in .* ===' cd .. -EXPECTED_TO_PASS=5223 +EXPECTED_TO_PASS=5238 PASSED=$(grep -a ' - Passed [0-9]* tests' dmdscript-test262.log | sed -n 's/.*Passed \([0-9]*\) tests.*/\1/;P') if [ "$PASSED" -gt "$EXPECTED_TO_PASS" ]; then From 3aa9957e3518c437fdad7647727c807f4bd18dd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Fri, 14 Jun 2024 22:48:06 +0200 Subject: [PATCH 4/5] Upload test log as build artifact and build with LDC. --- .github/workflows/ci.yml | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7bc6fd0..a733ef1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,44 +17,46 @@ jobs: matrix: os: [ubuntu-latest, windows-latest] dc: [dmd-latest, ldc-latest, ldc-1.15.0] - arch: [x86, x86_64] + arch: [x86_64] + include: + - {os: windows-latest, dc: ldc-latest, arch: x86} runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install D compiler - uses: dlang-community/setup-dlang@v1 + uses: dlang-community/setup-dlang@v2 with: compiler: ${{ matrix.dc }} - name: Run tests - env: - CONFIG: ${{matrix.config}} - ARCH: ${{matrix.arch}} shell: bash - run: dub test :engine + run: dub test :engine -a ${{matrix.arch}} testsuite: name: Test262 strategy: fail-fast: false matrix: os: [ubuntu-latest] - dc: [dmd-latest] - arch: [x86_64] + dc: [ldc-latest] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install D compiler - uses: dlang-community/setup-dlang@v1 + uses: dlang-community/setup-dlang@v2 with: - compiler: ${{ matrix.dc }} + compiler: ${{matrix.dc}} - name: Run tests - env: - CONFIG: ${{matrix.config}} - ARCH: ${{matrix.arch}} shell: bash run: ./run-test262.sh + + - name: Upload log + uses: actions/upload-artifact@v3 + if: always() + with: + name: runtest262 log + path: dmdscript-test262.log From d788f49580c91937c3d6d2060bcc6ba1dbc647be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Tue, 18 Jun 2024 11:17:57 +0200 Subject: [PATCH 5/5] Actually don't free values in RandAA.reserve. Fixes issues with corrupted values under GC load. --- engine/source/dmdscript/RandAA.d | 1 - 1 file changed, 1 deletion(-) diff --git a/engine/source/dmdscript/RandAA.d b/engine/source/dmdscript/RandAA.d index 82d6a03..53bf61d 100644 --- a/engine/source/dmdscript/RandAA.d +++ b/engine/source/dmdscript/RandAA.d @@ -510,7 +510,6 @@ public: // handle it. GC.free(cast(void*)this._keys); GC.free(cast(void*)this.flags); - GC.free(cast(void*)this.vals); static if(storeHash) {