Jump to content

  • Log In with Google      Sign In   
  • Create Account

Sir Ementaler

Member Since 09 Mar 2013
Online Last Active Today, 04:59 AM

Topics I've Started

Access violation when passing function to generic initialization list.

Yesterday, 07:54 AM

In AngelScript 2.31.1 WIP revision 2319, the following code causes an assertion failure, and if ignored, an access violation error:

funcdef bool Callback(int, int);
bool myGreaterThan(int a, int b) {
  return a > b;
bool myEquals(int a, int b) {
  return a == b;
bool myLessThan(int a, int b) {
  return a < b;
dictionary ops = {
  {"gt", @myGreaterThan},
  {"lt", @myLessThan},
  {"eq", @myEquals}

This error is exclusive to the $func type, i.e. won't occur if myCompare, myLessThan, and myEquals are assigned to handles of type Callback first and then those handles are passed to the initialization list. To remedy this temporarily script-side, I attempted making the following change to the ops definition:

dictionary ops = {
  {"gt", cast<Callback>(myGreaterThan)},
  {"lt", cast<Callback>(myLessThan)},
  {"eq", cast<Callback>(myEquals)}

This causes a different access violation without ever triggering an assertion failure. I didn't test whether the bugs are exclusive to initialization lists or also occur for generic function arguments.

Incorrect results from functions returning function handles.

30 April 2016 - 02:42 PM

Running AngelScript 2.31.1 WIP revision 2319, I have a script method registered in the following way:

ASengine->RegisterObjectMethod("Object", "func@ opCast()", asMETHOD(Object, operator asIScriptFunction*), asCALL_THISCALL);

where Object is a class and func is a funcdef. The method is implemented in such a way that it may return both null and non-null handles, but all results are considered null by the following script:

void main() {
	Object o;
	if (cast<func@>(o) is null)

I attempted to reproduce this using only a script, but the bug seems to occur only in application-registered functions. I spent some time debugging, and from what I understand, the function handle is erroneously placed into valueRegister instead of objectRegister because line 726 of as_callfunc.cpp doesn't predict function handles as returned types. Modifying the line to

if ( (descr->returnType.IsObject() || descr->returnType.IsFuncdef()) && !descr->returnType.IsReference() )

appears to fix the problem in this case.

Enum type conversion to int cost not calculated correctly.

18 April 2016 - 01:37 PM

Using one of the most recent revisions of AngelScript, one of our testers ran into a bug where the script was unable to pick the right overload for an enum type in the following circumstances:

enum e {val}
void f(int) {}
void f(int8) {}
void f(int16) {}
void f(int64) {}
void main() {

Essentially, neither of the int overloads is preferred by enum types (although signed int is preferred over unsigned). This was problematic, because our scripting interface exposes a method with a number of similar overloads that would ideally support any enum type, including user-defined ones. I was somewhat familiar with the way overload resolution works after research for my other recent report, which let me identify a likely source of the problem. The file as_compiler.cpp contains the following lines (beginning at line 5723 in our revision):

else if( to.GetSizeInMemoryBytes() || ctx->type.dataType.GetSizeInMemoryBytes() )

I believe that the || operator in this part was actually intended to be !=, i.e. a size conversion is to be performed when two types differ in size. Modifying it seemingly fixed the issue on our side.

Various unexpected behaviors of AngelScript 2.31.0

22 March 2016 - 10:07 AM

Ternary conditional operator applied to two null handles:

class foo {}
void main() {
	foo@ bar = true ? null : null;
Outcome: Compile error: Can't implicitly convert from '<null handle>' to 'foo@&'.
Expected outcome: Compiles, bar is initialized to null.
The expression has little use outside of temporary code / debugging, but it's reasonable to expect it to compile.
Auto initialized to null:
void main() {
	auto foo = null;
Outcome: Null pointer access in asCDataType::CanBeInstantiated, crash.
Expected outcome: Compile error or foo is of null handle type.

Again, there is typically no reason to do this, and it's not necessary that it compile, but ideally the engine would not crash when given incorrect code.


Return reference to void:

void& f() {
	return f();
Outcome: Compiles.
Expected outcome: Compile error: Data type cannot be reference to void.
Not very dangerous, because the only thing such a function can return is the result of another function that return void&, but this shouldn't be allowed to compile nonetheless.
Take reference to void:
void f(void &in, void &in) {}
void g() {}
void main() {
	f(g(), g());
Outcome: Assertion failure in asCCompiler::ConvertToVariable.
Expected outcome: Compile error: Data type cannot be reference to void.
A more malicious version of the previous issue.
Void value used as argument of function that takes no arguments.
void f() {}
void main() {
Outcome: Compiles, calls f twice.
Expected outcome: Compile error: Function f does not take arguments.

This is a bit of a special case, because I notice it's akin to C function definitions where functions that take no parameters are declared to take void, but wherever this kind of syntax is encountered, it appears to me that it's almost certain it's in error. Perhaps minimally a warning would be in place in this case.

Assert failure when passing function handle by reference.

01 March 2016 - 05:55 PM

I wasn't able to tell what the problem is here, but this code reliably reproduces it in AngelScript 2.31.0:

funcdef void f();
class foo {
	void opAssign(f@ &in) {}
void main() {
	foo bar = main;

Only happens with operator overloads.