Skip to content

Commit 8a48221

Browse files
committed
fix(zscript): disallow casting custom objects to unrelated types
A bug in type conversion allowed this code to compile: ```c++ Object obj = new Object(); int number = obj; int numbers[] = {obj}; ``` The above code now produces a compiler error.
1 parent bb644e0 commit 8a48221

File tree

4 files changed

+73
-4
lines changed

4 files changed

+73
-4
lines changed

src/parser/SemanticAnalyzer.cpp

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1979,13 +1979,41 @@ void SemanticAnalyzer::caseArrayLiteral(ASTArrayLiteral& host, void*)
19791979
program.getTypeStore().getCanonicalType(
19801980
DataTypeArray(elementType)));
19811981
}
1982-
1983-
// Otherwise, default to Untyped -Em
19841982
else
19851983
{
1984+
// No explicit type, try to infer one from elements.
1985+
const DataType* type = nullptr;
1986+
for (auto&& node : host.elements)
1987+
{
1988+
auto node_type = type = node->getReadType(scope, this);
1989+
if (node_type->isUntyped())
1990+
{
1991+
type = nullptr;
1992+
break;
1993+
}
1994+
1995+
if (!type)
1996+
{
1997+
type = node_type;
1998+
continue;
1999+
}
2000+
2001+
// I think this should accept only exactly matching types. A future
2002+
// change could modify this to accept the base type of two related types.
2003+
if (!type->canCastTo(*node_type) || !node_type->canCastTo(*type))
2004+
{
2005+
type = nullptr;
2006+
break;
2007+
}
2008+
}
2009+
2010+
// Fallback is to create an untyped array.
2011+
if (!type)
2012+
type = &DataType::UNTYPED;
2013+
19862014
host.setReadType(
19872015
program.getTypeStore().getCanonicalType(
1988-
DataTypeArray(DataType::UNTYPED)));
2016+
DataTypeArray(*type)));
19892017
}
19902018

19912019
// If initialized, check that each element can be cast to type.

src/parser/Types.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ bool DataTypeCustom::canCastTo(DataType const& target) const
673673
dynamic_cast<DataTypeArray const*>(&target))
674674
return canCastTo(getBaseType(*t));
675675

676-
if(!isClass())
676+
if(!isClass() && !isUsrClass())
677677
{
678678
if (DataTypeSimple const* t =
679679
dynamic_cast<DataTypeSimple const*>(&target))

tests/scripts/errors/errors_3.zs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#option NO_ERROR_HALT on
2+
3+
class Object {
4+
}
5+
6+
global script Global
7+
{
8+
void run()
9+
{
10+
Object obj = new Object();
11+
12+
// Invalid.
13+
int number = obj;
14+
obj = number;
15+
int numbers[] = {obj};
16+
Object objects[] = numbers;
17+
Object objects2[] = new Object(); // TODO: this should be invalid.
18+
19+
// OK.
20+
int numbers2[] = {obj, <untyped>1};
21+
Object objects3[] = {obj};
22+
auto objects4[] = objects3; // TODO: this should be valid.
23+
auto numbers3[] = {1, 2, 3}; // TODO: this should be valid.
24+
25+
// Invalid.
26+
numbers3 = objects4; // TODO: this should be invalid.
27+
}
28+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Compiling 'errors_3.zs'
2+
Pass 1: Parsing
3+
Pass 2: Preprocessing
4+
Pass 3: Registration
5+
Pass 4: Analyzing Code
6+
ZQ_BUFFER Line 13 @ Columns 13-25 - Error T017: Cannot cast from Object to int.
7+
ZQ_BUFFER Line 14 @ Columns 3-15 - Error T017: Cannot cast from int to Object.
8+
ZQ_BUFFER Line 15 @ Columns 7-24 - Error T017: Cannot cast from Object[] to int[].
9+
ZQ_BUFFER Line 16 @ Columns 10-29 - Error T017: Cannot cast from int[] to Object[].
10+
ZQ_BUFFER Line 22 @ Columns 8-29 - Error T017: Cannot cast from Object[] to auto[].
11+
ZQ_BUFFER Line 23 @ Columns 8-30 - Error T017: Cannot cast from int[] to auto[].
12+
Failure!
13+
Compile finished with exit code '17' (compiled with errors)

0 commit comments

Comments
 (0)