Skip to content

Conversation

@rodiazet
Copy link
Contributor

This PR adds additional check in TypeChecker for IndexAccess which ensures that the array size is not 0.
As a result of this change, type which is an empty array of contracts is also forbidden.

Fixes #13652.

@rodiazet rodiazet requested review from cameel and nikola-matic and removed request for nikola-matic January 23, 2026 15:42
@stackenbotten3000
Copy link

There was an error when running chk_coding_style for commit aa31d42a9b1c270b3d5024b70e97d60c34f33da8:

Coding style error:
libsolidity/analysis/TypeChecker.cpp:26:#include "DeclarationTypeChecker.h"

Please check that your changes are working as intended.


#include <libsolidity/analysis/TypeChecker.h>

#include "DeclarationTypeChecker.h"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coding style error

@stackenbotten3000
Copy link

There was an error when running chk_coding_style for commit 12c94081a054bcce42ac0aa36bf24a9360ee4bcc:

Coding style error:
libsolidity/analysis/TypeChecker.cpp:26:#include "DeclarationTypeChecker.h"

Please check that your changes are working as intended.


#include <libsolidity/analysis/TypeChecker.h>

#include "DeclarationTypeChecker.h"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coding style error

Copy link
Contributor

@nikola-matic nikola-matic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changelog

library C {
function f() view public {
C[0];
C[1];
Copy link
Collaborator

@cameel cameel Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also add new cases testing specifically for the case of zero length in a situation like this? Or do we have them already?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I'd add variants for interfaces for completeness.

And rename C here to L (we usually use C for a contract so it makes it easy to confuse things).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is specifically about decoding so I'd rename it to abi_decode_zero_length_array_type.sol. You can have int[0] in other situations and this test is not checking them.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, I'm assuming we already have coverage for those other cases, but maybe check whether that's the case. These are ones I can think of:

  • Variable declaration
    • Contract variable (uint[0] x;, mapping(uint => uint[0]) m;, function() returns (uint[0] memory) f;)
    • Local variable (uint[0] storage x;)
    • Function arguments and returns
    • Try/catch statement (try this.g() returns (uint[0] memory) {} catch (bytes memory b) {})
  • Tuple declaration ((uint[0] memory a, uint b) = ([], 1);)
  • Struct field (struct S { uint[0] x; })
  • Error and event parameters
  • Array allocation (new uint[0][](3); })
  • No-op statement consisting of just the type (uint[0];)

Technically, these but are disallowed for various other reasons in analysis, but are still valid syntax, so would not hurt to have them covered:

  • UDVT declaration (type U is uint[0];)
  • type() builtin (type(uint[0])).
  • Ternary operator (true ? uint[0] : uint[0])
  • Inline Array indexing ([uint[0]][0])

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see f6() is actually not decoding. I'd still split it into separate tests though.

@@ -0,0 +1,38 @@
contract C {
function f0() public {
abi.decode("", (int[0]));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
abi.decode("", (int[0]));
abi.decode("", (int[0]));

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also add the case from #13652 (comment). That one was not a compilation error so it's important that this no longer allowed:

contract C {
    function f() public returns (bytes memory) {
        return abi.encode(abi.decode("", (int[0])));
    }
}

Copy link
Collaborator

@cameel cameel Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also add a dedicated case for super (which is actually a type):

contract C {
    function f() public {
        super[0];
    }
}
contract C {
    function f() public {
        super[0] s;
    }
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interestingly, an array of super is a valid expression on its own (super[3];) even though you cannot use it in a variable declaration (super[3] s;). I think it should be disallowed in either case.

I suspect that we have more things like this. Would be good to take a look at DeclarationTypeChecker and compare what other checks it has for ArrayTypeName that we do not here. Perhaps we should extract them into a shared function to avoid such discrepancies in the future.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, pinging @matheusaaguiar to pay attention to this in test cases related to comptime. Looks like we have two places in the code where we evaluate array sizes. These should always behave the same way.

Also, WTF, why does every random issue recently turn out to be related to comptime one way or another :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

zero-length array types in expression context do not raise type errors

5 participants