Procházet zdrojové kódy

Fixing exception when filled expression produces out of bounds addresses

main
Rocketsoup před 1 rokem
rodič
revize
040c853287

+ 5
- 1
js/spreadsheet.js Zobrazit soubor

343
 
343
 
344
 			case CellExpressionOperation.Reference: {
344
 			case CellExpressionOperation.Reference: {
345
 				const refAddress = expr.arguments[0];
345
 				const refAddress = expr.arguments[0];
346
+				if (refAddress === null) {
347
+					throw new CellEvaluationException(`Invalid cell address`, '#REF');
348
+				}
346
 				const cell = this.#grid.cellAt(refAddress);
349
 				const cell = this.#grid.cellAt(refAddress);
347
 				if (cell === null) {
350
 				if (cell === null) {
348
 					throw new CellEvaluationException(`No cell at ${refAddress.name}`, '#REF');
351
 					throw new CellEvaluationException(`No cell at ${refAddress.name}`, '#REF');
1470
 		const exp = this.#tryExpression(tokens, start, end - 1, address);
1473
 		const exp = this.#tryExpression(tokens, start, end - 1, address);
1471
 		const columnIndex = address.columnIndex;
1474
 		const columnIndex = address.columnIndex;
1472
 		exp.fillRanges = [
1475
 		exp.fillRanges = [
1473
-			new CellAddressRange(new CellAddress(columnIndex, -1), new CellAddress(columnIndex, -1)),
1476
+			new CellAddressRange(new CellAddress(columnIndex, address.rowIndex), new CellAddress(columnIndex, 999999)),
1474
 		];
1477
 		];
1475
 		return exp;
1478
 		return exp;
1476
 	}
1479
 	}
1690
 		if (!tokens[start].type.isPotentialAddress()) return null;
1693
 		if (!tokens[start].type.isPotentialAddress()) return null;
1691
 		const ref = tokens[start].content.toUpperCase();
1694
 		const ref = tokens[start].content.toUpperCase();
1692
 		const refAddress = CellAddress.fromString(ref, address, true);
1695
 		const refAddress = CellAddress.fromString(ref, address, true);
1696
+		if (refAddress === null) return null;
1693
 		return new CellExpression(CellExpressionOperation.Reference, [ refAddress ]);
1697
 		return new CellExpression(CellExpressionOperation.Reference, [ refAddress ]);
1694
 	}
1698
 	}
1695
 
1699
 

+ 1
- 1
js/spreadsheet.min.js
Diff nebyl zobrazen, protože je příliš veliký
Zobrazit soubor


+ 11
- 0
jstest/spreadsheet/SpreadsheetMarkdownIntegrationTests.js Zobrazit soubor

60
 		this.assertEqual(expected, actual);
60
 		this.assertEqual(expected, actual);
61
 	}
61
 	}
62
 
62
 
63
+	test_observedError2() {
64
+		// A FILLed difference formula in row 2 of `=B2-B1` threw an exception
65
+		// due to a transposed address to the row above of `=B1-B0`.
66
+		const markdown = `| TB | Price | $/TB | Incr |
67
+| --- | --- | --- | --- |
68
+| 2 | $99.99 | =B/A FILL | |
69
+| 4 | $186.41 | | =B2-B1 FILL |
70
+| 6 | $209.99 | | |`;
71
+		const actual = this.md(markdown);
72
+	}
73
+
63
 	test_styledValue() {
74
 	test_styledValue() {
64
 		const markdown = "| A | B | C |\n| --- | --- | --- |\n| **3** | _4_ | =A*B |";
75
 		const markdown = "| A | B | C |\n| --- | --- | --- |\n| **3** | _4_ | =A*B |";
65
 		const expected = '<table><thead>' +
76
 		const expected = '<table><thead>' +

+ 5
- 1
php/spreadsheet.php Zobrazit soubor

302
 
302
 
303
 			case CellExpressionOperation::Reference: {
303
 			case CellExpressionOperation::Reference: {
304
 				$refAddress = $expr->arguments[0];
304
 				$refAddress = $expr->arguments[0];
305
+				if ($refAddress === null) {
306
+					throw new CellEvaluationException("Invalid cell address", '#REF');
307
+				}
305
 				$cell = $this->grid->cellAt($refAddress);
308
 				$cell = $this->grid->cellAt($refAddress);
306
 				if ($cell === null) {
309
 				if ($cell === null) {
307
 					throw new CellEvaluationException("No cell at {$refAddress->name}", '#REF');
310
 					throw new CellEvaluationException("No cell at {$refAddress->name}", '#REF');
1394
 		$exp = self::tryExpression($tokens, $start, $end - 1, $address);
1397
 		$exp = self::tryExpression($tokens, $start, $end - 1, $address);
1395
 		$columnIndex = $address->columnIndex;
1398
 		$columnIndex = $address->columnIndex;
1396
 		$exp->fillRanges = [
1399
 		$exp->fillRanges = [
1397
-			new CellAddressRange(new CellAddress($columnIndex, -1), new CellAddress($columnIndex, -1)),
1400
+			new CellAddressRange(new CellAddress($columnIndex, $address->rowIndex), new CellAddress($columnIndex, 999999)),
1398
 		];
1401
 		];
1399
 		return $exp;
1402
 		return $exp;
1400
 	}
1403
 	}
1624
 		if (!$tokens[$start]->type->isPotentialAddress()) return null;
1627
 		if (!$tokens[$start]->type->isPotentialAddress()) return null;
1625
 		$ref = mb_strtoupper($tokens[$start]->content);
1628
 		$ref = mb_strtoupper($tokens[$start]->content);
1626
 		$refAddress = CellAddress::fromString($ref, $address, true);
1629
 		$refAddress = CellAddress::fromString($ref, $address, true);
1630
+		if ($refAddress === null) return null;
1627
 		return new CellExpression(CellExpressionOperation::Reference, [ $refAddress ]);
1631
 		return new CellExpression(CellExpressionOperation::Reference, [ $refAddress ]);
1628
 	}
1632
 	}
1629
 
1633
 

+ 8
- 0
phptest/spreadsheet/SpreadsheetMarkdownIntegrationTests.php Zobrazit soubor

74
 		$this->assertSame($expected, $actual);
74
 		$this->assertSame($expected, $actual);
75
 	}
75
 	}
76
 
76
 
77
+	public function test_observedError2() {
78
+		// A FILLed difference formula in row 2 of `=B2-B1` threw an exception
79
+		// due to a transposed address to the row above of `=B1-B0`.
80
+		$markdown = "| TB | Price | $/TB | Incr |\n| --- | --- | --- | --- |\n| 2 | $99.99 | =B/A FILL | |\n| 4 | $186.41 | | =B2-B1 FILL |\n| 6 | $209.99 | | |";
81
+		$actual = $this->md($markdown);
82
+		$this->assertTrue(true);
83
+	}
84
+
77
 	public function test_styledValue() {
85
 	public function test_styledValue() {
78
 		$markdown = "| A | B | C |\n| --- | --- | --- |\n| **3** | _4_ | =A*B |";
86
 		$markdown = "| A | B | C |\n| --- | --- | --- |\n| **3** | _4_ | =A*B |";
79
 		$expected = '<table><thead>' .
87
 		$expected = '<table><thead>' .

Načítá se…
Zrušit
Uložit