Giter Club home page Giter Club logo

pawn's People

Contributors

33127530 avatar alexgoldstone avatar avykhovanets avatar compuphase avatar daniel-cortez avatar namazso avatar pbartruff avatar peace-maker avatar vvirvicius avatar wpmgprostotema avatar zboszor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pawn's Issues

stringize operator

From "pawn language guide"
If an argument in the replacement text has a “#” immediately in front of it, the argument is converted to a packed string constant —meaning that double quotes are tagged at the beginning and the end.

so, this code

#include <console>
#define STR(%1) #%1

main()
{
    printf(STR("TEST"));
}

has compile error. Maybe "stringize" has to involves more than putting double-quote characters around the fragment (backslash-escapes the quotes surrounding embedded string constants) ?

Request: standalone references?

Is it alright that I request Pawn to have standalone references like C++ does?

new i = 5;
new &p = i;
p = 9; // i is now 9

Perhaps denote it by giving it a different operator?
modified example above

new i = 5;
new @p = i;
p = 9; // i is now 9

Same example above but with floating point.

new float:f = 5.02;
new &float:p = f;
p = 3.14; // f is now 3.14

Garbage collector problems

The simple garbage collector in amxgc.c appears to have a few issues which lead to loops never terminating. If the table has filled up and gc_mark is called, then the condition if (SharedGC.count>=(1<<SharedGC.exponent)) in gc_mark, which is for enlarging the table, is never true because it appears that SharedGC.count is always zero. The only assignments to SharedGC.count set it to 0. (The naming of count is perhaps unfortunate because there are two of them, one in GCPAIR and one in GCINFO and both appear to have totally different uses.) Since the table is not enlarged the while loop in gc_mark cannot find a free entry and never terminates.

Furthermore, scansection has two while loops and the inner one will loop forever if the table is full and the value in *start cannot be found (which is likely) and the table has no free entries.

I am unsure what the search algorithm is trying to achieve, i.e. with the "folding" etc. It appears to be trying to implement something that is faster than a simple linear search but without more information on the algorithm I don't feel like modifying the while loop in scansection.

Not a bug but just out of curiosity, what is the point of the inverse array? What does *minorbyte=inverse[*minorbyte] do that *minorbyte=~(*minorbyte) or *minorbyte=255 - *minorbyte does not?

amx_InitJIT bug

"hdr" isn't initialized while checking file_version

int AMXAPI amx_InitJIT(AMX *amx, void *reloc_table, void *native_code)
{
  int res;
  AMX_HEADER *hdr;

  if ((amx->flags & AMX_FLAG_JITC)==0)
    return AMX_ERR_INIT_JIT;    /* flag not set, this AMX is not prepared for JIT */
  if (hdr->file_version>MAX_FILE_VER_JIT)
    return AMX_ERR_VERSION;     /* JIT may not support the newest file version(s) */
  /* the JIT does not support overlays, but this is already checked in VerifyPcode()
   * the same goes for macro instructions: not supported in the JIT, but already
   * checked in VerifyPcode()
   */

strins ignores the "maxlength" parameter

Original credit goes to @oscar-broman for discovering this bug.

Test code:

#include <console>
#include <string>
main()
{
    const cellbytes = cellbits / charbits;
    static const substring{} = "012";
    static buffer1{} = "3456789";
    static buffer2{4 * cellbytes} = {255, 255, ...};
    strins(buffer1, substring, 0);
    new bool: overrun_detected = false;
    for (new i = 0; i < sizeof(buffer2) * cellbytes; ++i)
        if ((overrun_detected = (buffer2{i} != 255)) == true)
            break;
    printf("buffer1 contents:");
    for (new i = 0; i < sizeof(buffer1) * cellbytes; ++i)
        printf(" %d", buffer1{i});
    printf("\n");
    printf("buffer2 contents:");
    for (new i = 0; i < sizeof(buffer2) * cellbytes; ++i)
        printf(" %d", buffer2{i});
    printf("\n");
    printf(overrun_detected ? "Buffer overrun detected!\n" : "Test passed\n");
}

Output:

buffer1 contents: 48 49 50 51 52 53 54 55
buffer2 contents: 56 57 0 255 255 255 255 255 255 255 255 255 255 255 255 255
Buffer overrun detected!

Unrelatedly, at the beginning of amxexec_arm7_gas.s and amxexec_thumb2_gas.s I found this:
This file assembles with GUN's AS (GAS).
This is just a grammar mistake, not a real bug, so I guess it's better to mention it here instead of creating a new issue.

Missing coding conventions?

I'm not sure is this right place to ask, but where can I find PAWN coding convention references for PAWN coding standards?
Like naming of variables, functions, consts, arrays, folders, files etc...

OOB access in `findfunction`

for (i=0; list[i].name!=NULL && (i<number || number==-1); i++)

Checks list[i].name before checking i < number, which is OOB when using an exact count and no sentinel entry. See:

Zeex/sampgdk#188

Edit: Not an overflow, since nothing is written, but still OOB.

Export project

Please export pawnscript to GitHub.

Google Code:

"August 24, 2015 - The site goes read-only. You can still checkout/view project 
source, issues, and wikis.
January 25, 2016 - The project hosting service is closed. You will be able to 
download a tarball of project source, issues, and wikis. These tarballs will be 
available throughout the rest of 2016."

Original issue reported on code.google.com by [email protected] on 30 Jun 2015 at 3:08

Not defined AMX_FLAG_COMPACT used when BYTE_ORDER is set to BIG_ENDIAN

pawn-4.0.5749

in file "amx.c"

amx_Init()
{
...
#if BYTE_ORDER==BIG_ENDIAN
if ((hdr->flags & AMX_FLAG_COMPACT)==0) {
ucell *code=(ucell *)((unsigned char *)program+(int)hdr->cod);
while (code<(ucell *)((unsigned char )program+(int)hdr->hea))
amx_SwapCell(code++);
} /
if */
#endif
...
}

labels with the same name

Originally discovered at pro-pawn.ru by a forum member nicknamed Blood:
http://pro-pawn.ru/showthread.php?14157

The compiler allows to make labels with the same name within a function scope.
If one defines two or more labels with identical names and use goto to one of those labels, the compiler will make a jump at the last label with that name.
Sometimes this can lead to unexpected (or unintuitive) results.

Example:

#include <console>

main()
{
    goto test_label;
test_label:
    print("test_label 1\n");
    return;
test_label:
    print("test_label 2\n");
}

One might expect it to print "test_label 1", but it actually outputs "test_label 2".
The compiler warns about unreachable code (even though goto test_label leads right to that code), but it doesn't even tell anything about the second test_label shadowing the first one.
Normally I'd ask if this is a bug or it's intended to be so, but since Pawn is designed to be a robust language, I guess this should be considered a bug. The compiler should either disallow using the same name for labels more than once per function or at least give a warning message.

tagof(<tag name>:) in a switch statement bug

This bug was originally discovered by @ziggi.

#include <console>
#include <float>

stock PrintInt(i)
    printf("int: %d\n", i);

stock PrintFloat(Float:f)
    printf("float: %f\n", f);

stock PrintBool(bool:b)
    printf("bool: %s\n", (b)?("true"):("false"));

stock Print({_, Float, bool}:arg, arg_tag=tagof(arg))
{
    switch(arg_tag)
    {
        case tagof(Float:):             // Line 17
            PrintFloat(Float:arg);
        case tagof(bool:):
            PrintBool(bool:arg);
        default:
            PrintInt(_:arg);
    }
}

main()
{
    print("--Function overloading emulation test--\n");
    Print(1);
    Print(1.0);
    Print(true);
}

When I try to compile this the compiler shows a bunch of error messages:

test.p(17) : error 081: expression with tag override must appear between parentheses
test.p(17) : error 029: invalid expression, assumed zero
test.p(19) : warning 217: loose indentation
test.p(19) : error 014: invalid statement; not in switch
test.p(19) : warning 215: expression has no effect
test.p(19) : error 001: expected token: ";", but found ":"
test.p(19) : error 029: invalid expression, assumed zero
test.p(19) : fatal error 107: too many error messages on one line
6 Errors.
Compilation aborted.

But if I put the tagof expressions into parentheses...

        case (tagof(Float:)):               // Line 17
            PrintFloat(Float:arg);
        case (tagof(bool:)):
            PrintBool(bool:arg);

... the code compiles and works normally.

Linux x86-64 Build Fails

What steps will reproduce the problem?
1. Acquire a 64-bit GNU/Linux installation
2. Attempt to compile PAWN
3. Behold the error log

What is the expected output? What do you see instead?
I expect to see the program build, but instead I see numerous errors regarding 
integers of one size being assigned to integers of a smaller size, which is a 
classic 64-bit portability problem.

What version of the product are you using? On what operating system?
PAWN 4.0.4733 and PAWN SVN July 27, 2012 on Arch Linux (rolling-release).

Please provide any additional information below.
This problem seems to indicate that PAWN is not portable to 64-bit 
architectures (or, at least, 64-bit GNU/Linux).

Original issue reported on code.google.com by Luiji99 on 28 Jul 2012 at 4:39

Cannot create entry or exit functions for multiple automations

When multiple automations are created only the entry and exit functions can be used for a single automation. For example:
entry() <s1: A1> { print("A1"; }
entry() <s1: A2> { print("A2"; }
entry() <s2: B1> { print("B1"; }
entry() <s2: B2> { print("B2"; }

Results in error 084: state conflict: one of the states is already assigned to another implementation ( symbol "entry").

It would be nice to use the automation rather than formulate a custom framework.

Bad codegen with error in operator overload.

native printf(const str[], ...);

operator=(Tag:x)
{
	return _:x:
}

main()
{
	new a = Tag:5;
	printf("%d", a);
}

This code should define a custom assignment operator for Tag:, and call it. Instead, it gives an unused symbol warning for the operator= and generates no code at all. Compiling with -a gives:

CODE 0	; 0
;program exit point
	halt 0


STKSIZE 1000

Literally a totally blank AMX.

Note: This took a while to spot. I found the original bug here pawn-lang/compiler#387 and attributed it to the operator somehow, but @YashasSamaga was the one who noticed my typo, the root cause. I wrote _:x: instead of _:x; - a colon not a semi-colon, and very hard to spot. This should give a syntax error and not compile, but somehow messes up. I do know some errors are ignored when the function isn't used, which should be the case were it not, but it is. I think the fact that its an operator overload confuses that part of the compiler as well.

Segmentation fault when using amx*.so under Ubuntu 16.04 64-bit

Hi

I tried different versions of Pawn under Ubuntu 16.04 64-bit: latest from github, 4.0.57.49 ZIP arvhive.
Compile OK with just issuing commands: cmake . && make

When I try simple examples like "Hello World!" - all works fine.

But when I try to add to my Pawn code <args> or <datagram> it falls with segmentation fault and gdb backtrace shows the following:

Program received signal SIGSEGV, Segmentation fault.
0x00000000f75fe004 in ?? ()
(gdb) bt
#0  0x00000000f75fe004 in ?? ()
#1  0x0000000000403933 in amx_Callback ()
#2  0x0000000000407a80 in amx_Exec ()
#3  0x0000000000403280 in main ()

What I'm doing wrong?

Thanks!

Optimizer messes up subtraction

1. Compile the attached pawn_sub_bug.pawn with option -O2:
$ pawncc -O2 pawn_sub_bug.pawn

2. Run it:
$ pawnrun pawn_sub_bug.amx 
Return value: -160

Expected value was +160.

Apparently the semantics of sub and sub.inv were changed sometime before Pawn 
4, but the peephole optimizer was not updated to match. Here is a complete 
patch, which is quite messy as I re-ran scpack:
https://github.com/PetteriAimonen/QuadPawn/commit/a80179d4e171203930cb9066b0511c
dd29b43392

The core of the patch is around line 1530 in sc7.scp:
    *    --------------------------------------
-   *    const.alt %1            add.c -%1
+   *    const.pri %1            add.c -%1
    *    sub                     -

(Thanks to David Schwartz for finding this bug.)

Original issue reported on code.google.com by Petteri.Aimonen on 2 Jun 2012 at 8:13

Attachments:

Documentation source

The repo only has the pdf versions of Pawn_Language_Guide etc. It would be nice to be able to update those as well.

"Standard library" function calls cause program to crash

I am getting a segmentation fault on 64-bit Linux Mint on this file:

#include <console>

main()
{
  printf("hello\n");
}

Compile string is pawncc -C:64 hello.p, pawncc is compiled with -DHAVE_I64 -DPAWN_CELL_SIZE=64, pawnrun is compiled with AMX_ALTCORE (GNU extensions). This segfault traces back into amx_Exec->amx_exec_run->first NEXT instruction, it executes 7 times then crashes. Corresponding macro expansion is
#define NEXT(cip,op) goto *amx_opcodelist[(op=*cip++) & ((1 << sizeof(cell)*4)-1)]
My knowledge of underlying procedures ends here.

When compiling without AMX_ALTCORE, the same behaviour occurs: execution reaches the main for ( ;; ) loop, does 7 iterations and crashes successfully.

If I substitute printf with print in pawn code, it crashes after 13 iterations.

It seems that the segfault occurs with every native function that *.inc files in pawn toolkit provide (even with clamp; some other functions cause just run-time errors).

This problem arises in 32-bit pawn codes too, so I moved this post out of 64-bit thread into a new one.

How to get process exit code?

Could you, please, show how to get process exit code?

My attempt (does not work):

#include <process>
main()
{
    new PID:pr = procexec("7z t \"archive.zip\"")
    printf "PID:%d\n", pr
    if (pr != 0)
    {
        procwait(pr)
        new ec = 0
        libcall("kernel32", "GetExitCodeProcess", "uu", pr, ec)
        printf "Exit Code:%d\n", ec
    }
}

#warning directive

Can you add something like #error but for creating user warnings? And something like #pragma warning for adding new warnings and disabling/enabling existing.

This implemented in fork of Pawn 3.2.3664 by Zeex: https://github.com/Zeex/pawn/wiki/What's-new#pragma-warning

#warning

Print a user warning.

This works similar to the #error directive. For example, compiling a file
that contains

#warning Don't include this file

would result in

warning 237: user warning: Don't include this file

#pragma warning

This directive comes in two forms:

  • #pragma warning (enable|disable) XXX

    Enable or disable a warning by its number.

    Useful for hiding unwanted warnings that otherwise cannot be fixed.

  • #pragma warning (push|pop)

    Save or restore the list of currently disabled warnings.

    This can be used in conjuction with the previous form to toggle warnings
    for a piece of code:

    #pragma warning push
    #pragma warning disable XXX
    // some code here
    ...
    #pragma warning pop

[alt] behaviour in OP_STACK makes no sense.

OP_STACK is defined as:

STACK | value | ALT = STK, STK = STK + value

That means the current stack position is placed in to alt, then the stack is adjusted. This is used in two ways:

  1. To shrink the stack after some usage. This will mean that after the call alt now points below the stack to invalid memory.

  2. To expand the stack for more data. This will mean that after the call alt will point to the old data that was already on the stack.

I have never ever seen a good use for this behaviour - it makes perfect sense for OP_HEAP because that grows up, and so after expansion alt will point to the start of the new data. In this opcode it is entirely useless. Much better would be:

STK = STK + value, ALT = STK

When growing the stack, that will mean ALT now points to the start of the newly allocated data, ready for use. When shrinking the stack, that will mean ALT still points to valid memory.

I very frequently have to do:

#emit STACK 20
#emit STACK 0

Just to adjust the stack then get the new pointer. I've never once needed the old pointer (and on the rare case I did, could just swap those over). I know #emit isn't used, but I think it would benefit the compiler as well to already have the new memory locations.

Build fixes for OS X

Current versions of pawnscript (through 4.0-4733) do not build cleanly using 
CMake on OS X due to a number of issues:

 - libraries built as part of AMX aren't using modern visibility attributes, and depend on the -K argument to strip, which is not compatible with the way the OS X toolchain handles exports.
 - neither amx nor the compiler are 64-bit clean, and OS X defaults to building 64-bit binaries
 - there are many missing ifdef __APPLE__ cases in the code
 - directory separator is / not :
 - assorted other minor issues (stime vs. settimeofday, __T, etc.)

Attached is a port to 4733 of a patch that worked in light testing on 4548.

Original issue reported on code.google.com by [email protected] on 12 Aug 2012 at 5:42

Attachments:

The use of waitpid requires <sys/wait.h> to be included

I tried building the compiler using Alpine and Ubuntu linux. Both output the following warning:

/home/pawn/compiler/sc1.c: In function 'posix_spawnl':
/home/pawn/compiler/sc1.c:460:5: warning: implicit declaration of function 'waitpid' [-Wimplicit-function-declaration]
  460 |     waitpid(pid,&stat,0);
      |     ^~~~~~~

Undocumented behavior of strcmp

If one of the strings is empty, strcmp returns the difference of their lengths, but the documentation (String_Manipulation.pdf) says that strcmp can only return 1, 0 or -1.
Example:

#include <console>
#include <string>
main()
{
    static const test_strings[4]{12} = ["", "123", "abc", "hello world"];
    for (new i = 0; i < sizeof(test_strings); ++i)
        for (new j = 0; j < sizeof(test_strings); ++j)
            printf("strcmp(\"%s\" \"%s\"): %d\n",
                test_strings[i], test_strings[j],
                strcmp(test_strings[i], test_strings[j]));
}

Output:

strcmp("" ""): 0
strcmp("" "123"): -3
strcmp("" "abc"): -3
strcmp("" "hello world"): -11
strcmp("123" ""): 3
strcmp("123" "123"): 0
strcmp("123" "abc"): -1
strcmp("123" "hello world"): -1
strcmp("abc" ""): 3
strcmp("abc" "123"): 1
strcmp("abc" "abc"): 0
strcmp("abc" "hello world"): -1
strcmp("hello world" ""): 11
strcmp("hello world" "123"): 1
strcmp("hello world" "abc"): 1
strcmp("hello world" "hello world"): 0

Is this a bug or just an undocumented feature?

instruction to compile pawn on windows in msys2+mingw?

Is there any such instruction to do so?
I have give it a try

first, alloca.h is reported to be missed in amx.h, so I leave #include <malloc.h> in amx.h.

then,

$ make
[  3%] Built target pawndisasm
[ 32%] Built target pawncc
[ 37%] Built target stategraph
[ 38%] Linking C shared library ../amxString.dll
gcc.exe: error: /export:amx_StringInit: No such file or directory
gcc.exe: error: /export:amx_StringCleanup: No such file or directory
make[2]: *** [amx/CMakeFiles/amxString.dir/build.make:115: amxString.dll] Error 1
make[1]: *** [CMakeFiles/Makefile2:218: amx/CMakeFiles/amxString.dir/all] Error 2
make: *** [Makefile:84: all] Error 2

Conditional compiled sections with "late" definitions, cause code generation errors

Reported by Alex Cole on the forum.
The following code generates invalid code on Pawn 3 and makes the compiler drop into an assertion on Pawn 4.

new gVar;

stock SomeFunction()
{
#if defined main
    gVar = (gVar ? 0 : 1);
#endif
    return 0;
}

main()
{
    return SomeFunction() ? 0 : 1;
}

The cause turns out to be that the assignment of gVar is skipped on the first pass that the compiler makes through the code (because "main" is undefined at that point), but it is included on the second pass (because "main" has been seen since). It is usually not a problem when the second pass sees different code than the first pass, but there are exceptions, and this is one of them.

The suggested change is that the first pass is repeated in a case like the above, so that on the next iteration of that "first" pass, the compiler sees exactly the same code path as what the second pass goes through.

Feature request: /nologo option

Not really a bug, but a feature request: would like an option like the MS
compilers - /nologo - to hide the initial banner that displays during a
compile.



Original issue reported on code.google.com by [email protected] on 2 Jan 2007 at 4:50

Incorrect documentation

image
here where the documentation says STK = STK + [STK] which would add the return address to STK
image
here, the range is actually filled with PRI, rather than [PRI]

Assertion when using named array index

Using Pawncc 4.0.4733 compiling attached script gives following assertion 
output:

Assertion Failed: cval!=NULL && cval->next!=NULL, function hier1, file sc3.c, 
line 1870.
ABNORMAL TERMINATION

Original issue reported on code.google.com by [email protected] on 7 Dec 2012 at 10:26

Attachments:

ALS7 hooking method

In Pawn 3.2 it was possible to "hook" a function using a compiler bug. Preprocessor handled "#if defined" statements in a second-round of preprocessing, read more here.

Now it's not working, because the bug was fixed. Please, return that behaviour, because ALS hooking is a critical functionality.

Colors in IDE

Are they broken or did i just fail to understand what they change?

image

another array initialization bug

Recently I encountered a bug with 2-dimensional array initialization. The compiler seems to insert extra cells before the array contents.
Here's a reproduction:

#include <console>

main()
{
    static const my_array[3][3] =
    [
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9],
    ];
    for (new i = 0; i < sizeof(my_array); ++i)
        for (new j = 0; j < sizeof(my_array[]); ++j)
            printf("my_array[%d][%d] = %d\n", i, j, my_array[i][j]);
}

Normally the output should be:

my_array[0][0] = 1
my_array[0][1] = 2
my_array[0][2] = 3
my_array[1][0] = 4
my_array[1][1] = 5
my_array[1][2] = 6
my_array[2][0] = 7
my_array[2][1] = 8
my_array[2][2] = 9

But instead I got this:

my_array[0][0] = 0
my_array[0][1] = 1
my_array[0][2] = 2
my_array[1][0] = 3
my_array[1][1] = 4
my_array[1][2] = 5
my_array[2][0] = 6
my_array[2][1] = 7
my_array[2][2] = 8

I decided to disassemble the .amx with pawndisasm, but before doing that I added the __start and the __end arrays so it would be easier to track the contents of my_array in disassembler output.

    static const __start{} = "___";
    static const my_array[3][3] =
    [
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9],
    ];
    static const __end{} = "___";
    #pragma unused __start, __end

And here's what the data section contains:

;DATA
00000000  5f5f5f00 0000000c 00000014 0000001c  ___             
00000010  00000000 00000001 00000002 00000003                  
00000020  00000004 00000005 00000006 00000007                  
00000030  00000008 00000009 5f5f5f00 6d795f61          ___ my_a
00000040  72726179 5b25645d 5b25645d 203d2025  rray[%d][%d] = %
00000050  640a0000  d   

5f5f5f00 is obviously the __start array and 00000001 00000002 ... 00000009 are the contents of my_array, but there are four cells between those two arrays: 0000000c 00000014 0000001c 00000000 - where do they come from?

This bug exists in both 4.0.4733 and the latest development version.

Pawn fails to compile when linking against ncurses that has been built with tinfo

Pawn's build system doesn't use FindCurses from cmake, and instead attempts to find ncurses itself. This leads to an error if ncurses has been built with a separate terminfo library (libtinfo). The FindCurses module from cmake copes with this by checking for a specific function to determine whether libtinfo has been split into a separate library or not (the cbreak function), and if so sets the libraries to link against appropriately.

Pawn doesn't make use of cbreak, but does use nodelay, however the cbreak check should still be sufficient.

Ideally this would be fixed by making use of cmake's pre-packaged FindCurses module, rather than custom implementing similar functionality. Failing that, the curses finding cmake code should take into account the potential need to link against libtinfo.

If you have any further question, please just let me know. For more information please see:

Cmake commit 1f646c6c
Gentoo bug 468622

Assertions on using conditional operator with functions that return array

Originally was reported and discussed here and here.

First case (function's definition located after call point):

main()
{
   printf(true ? f() : "Hello World!\n")
}

f() {
    new arr[256];
    return arr;
}

Assertion:

pawn/compiler/sc3.c:1296: hier13: Assertion `sc_status!=statWRITE || heap1==heap2' failed.

Online proof.
If I place the definition before call point then there is no assertion: online proof.

Second case (nested conditional with function's definition before call point):

f() {
    new arr[256];
    return arr;
}

main()
{
   printf(true ? (true ? f() : "Hello World!\n") : "Something")
}

Assertion:

pawn/compiler/sc3.c:1296: hier13: Assertion `sc_status!=statWRITE || heap1==heap2' failed.

Online proof. true ? (true ? "Hello World!\n" : f()) : "Something" and true ? (true ? "Something" : "Hello World!\n") : f() produce an assertion too. Cases where there are two f() also produce an assertion. Only the case where there are three f() have no assertions: proof.

multi-dimensional array initialization

I am having an issue on 4.0.4733 with properly initializing multi-dimensional arrays. The following example will demonstrate the problem.

main()
{
    new dropDownStrings[][]{} = [ ["Never","Niemals"] , ["Warning_Only","Nur Warnung"] ,["Reject_Only","Nur_Toleranz"] , ["Warning_or_Reject","Warnung_oder_Toleranz"] ] ;
    for(new a = 0; a < 4; a++)
        for(new b = 0; b < 2; b++)
        {
            print  dropDownStrings[a][b];
            print "\n";
        }
}

I would expect the output:
Never
Niemals
Warning_Only
Nur Warnung
Reject_Only
Nur_Toleranz
Warning_or_Reject
Warnung_oder_Toleranz

but instead I get this:
Never
Niemals
Warning_Only
Only
Nur Warnung
ung
Nur_Toleranz

It looks like the compiler sees the first entry is (in my case) 2 cells long and makes some assumptions about the rest of the initializer. Making the first string very long fixes this. Another quick workaround was to explicitly state a length of the last dimension of the array:
dropDownStrings[][]{25}

Is this a bug or am I dong something wrong?

Another vulnerability related to PUSHR* opcodes

I originally reported this vulnerability back in May through E-Mail because I didn't want to make the information about it publicly available, but apparently no actions were taken to fix it. And since there are other unfixed vulnerabilities some of which are known for years (see issue 26), I guess now there's no harm in reporting it here.

So...
Since Pawn 4.0 there are new PUSHR* opcodes that push a physical address of a cell instead of a "virtual" address in the VM as it was done previously with the PUSH* opcodes.
PUSHR* opcodes are used to pass variadic function arguments, pass-by-reference arguments and arrays. For all of the other cases Pawn Compiler still generates PUSH* opcodes.
But there's a way to trick the compiler to make it use PUSHR* opcodes where it should actually use PUSH* and vice versa.

// native valstr(dest[], value, bool:pack=true);
native GetArrPhysAddrAsStr(dest[], const value[], bool:pack=true) = valstr;

In this example I made an "alternate" definition for valstr. Note that the value argument is an array, not a single cell, so instead of the value of a given cell the array address is passed to valstr and the function returns that address as a string.
Retrieving the address of a single variable is possible as well:

native GetVarPhysAddrAsStr(dest[], const &value, bool:pack=true) = valstr;

And since addresses in Pawn 4.0 are passed with the PUSHR* opcodes, they're physical, not virtual.

After retrieving the address as a string it can be converted back to an integer:

native GetArrPhysAddrAsStr(dest[], const value[], bool:pack=true) = valstr;
stock GetArrPhysAddr(const arr[])
{
	// min value for a 64-bit cell: −9223372036854775808 (20 characters)
	new str{21};
	GetArrPhysAddrAsStr(str, arr, true);
	return strval(str);
}

It's also possible to utilize memcpy for read/write operations:

#include <console>
#include <string>

native GetDataByPhysAddr(dest[], src_addr, index=0, numbytes, maxlength=sizeof dest) = memcpy;
native SetDataByPhysAddr(dest_addr, const src[], index=0, numbytes, maxlength) = memcpy;
native GetArrPhysAddrAsStr(dest[], const value[], bool:pack=true) = valstr;

stock GetArrPhysAddr(const arr[])
{
	new str{21};
	GetArrPhysAddrAsStr(str, arr, true);
	return strval(str);
}

main()
{
	static const test_string{128} = "Hello";
	printf("Before: %s\n", test_string);
	static const new_string{} = "Hell no";
	new test_string_phys_addr = GetArrPhysAddr(test_string);
	SetDataByPhysAddr(
		test_string_phys_addr, new_string,
		0, sizeof(new_string) * (cellbits / charbits), 16
	);
	printf("After: %s\n", test_string);
}

Output:

Before: Hello
After: Hell no

That way it's even possible to write outside of the script memory and probably execute arbitrary bytecode by modifying the contents of the code section.

Removing the syntax for "alternate" function prototypes (like GetDataByPhysAddr, SetDataByPhysAddr and GetArrPhysAddrAsStr in the examples above) won't solve the problem because it still would be possible to do something like this:

#pragma library String  // instead of including string.inc
native memcpy(dest_phys_addr, const src[], index=0, numbytes, maxlength);
#define SetDataByPhysAddr memcpy

Also in this function prototype

native SetDataByPhysAddr(dest_addr, const src[], index=0, numbytes, maxlength) = memcpy;

note that the dest_addr argument is a single cell so the write address will be passed with one of the PUSH* opcodes, not PUSHR*. This means that adding address checks to all of the PUSHR* opcodes is pointless as well.

The only good fix I can think of is completely removing all of the PUSHR* opcodes from the instruction set, but that would require bringing back the amx_GetAddr function and probably some other actions to take.

Misc. vulnerabilities in LREF.S.*, SREF.S, SCTRL, RET, RETN and Jxx opcodes

  1. SCTRL opcode doesn't validate the value in PRI. It's possible to execute unverified P-code (SCTRL 6, just as in the CALL.PRI/JUMP.PRI vulnerability that was fixed in Pawn 3.3) and make hea, frm and/or stk point outside of the script memory block (SCTRL 2, 4, 5).
  2. RET and RETN opcodes don't check if the return address is negative. That check is performed statically (in VerifyPcode) for CALL, CASETBL and the jump opcodes though.
  3. SCTRL, RET, RETN, CALL, CASETBL and all of the jump opcodes don't check if the jump/return address is a multiple of cell size. That way it's possible to make the Abstract Machine misinterpret the P-code.
  4. LREF.S.pri, LREF.S.alt, SREF.s, LREF.P.S.pri, LREF.P.S.alt and SREF.P.s don't validate the address stored in the specified cell, this can be exploited to read/write data outside of the script memory block.

These vulnerabilities are rather hard to exploit since the #emit directive was removed long ago, but it's still possible to modify a compiled script with a hex editor or make a some kind of AMX assembler by reusing parts of code from the Pawn compiler.
Also I don't take credit for discovering all of the abovementioned vulnerabilities. The LREF.S.*/SREF.S one is already long known in the SA-MP community and used in several works (e.g. in the YSI includes for reading misc. AMX info) and the other ones were relatively easy to find.

amxexec_arm7.s does not build with RealView arm compiler

What steps will reproduce the problem?
1. Include amxexec_arm7.s in a RealView project
2. Compile
3. See errors below (PUSH and POP already known by armasm)

What is the expected output? What do you see instead?

Warning : A1480:  Macro cannot have same name as a directive or instruction
amxexec_arm7.s line 255   

Warning : A1480:  Macro cannot have same name as a directive or instruction
amxexec_arm7.s line 260   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 586   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 590   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 595   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 601   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 607   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 611   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 615   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 635   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 641   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 642   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 652   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 653   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 670   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 675   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 1188   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 1244   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 1315   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 1348   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 1353   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 1358   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 1363   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 1366   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 1372   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 1377   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 1382   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 1387   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 1390   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 1395   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 1399   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 1403   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 1407   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 1409   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 1416   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 1422   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 1428   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 1434   

Error   : A1215:  Bad register list symbol
amxexec_arm7.s line 1438   

armasm : 37 Errors, 2 Warnings


Error   : armasm Compile exit status = 2



What version of the product are you using? On what operating system?
Windows XP compiler for ARM7TDMI

Please provide any additional information below.

I was able to change all occurances of "PUSH" to "PUSHON" and "POP" to
"POPOFF" and then it compiled ok.

Original issue reported on code.google.com by [email protected] on 29 Dec 2006 at 6:39

Compilation of fib.p example cause infinite loop

Version of compiler is 4.0.5749.

OS Windows 10, compiler is MS Visual C++ 2019.

Code will be looping infinitely, slowly growing in memory,
while (!matchtoken('}')){ /* repeat until compound statement is closed */
file sc1, line 5900

Couse is, file fib1.p is UTF8 with UNIX LF line termination, after changing it to CR LF - compiled just fine.
Another fix is to add semicolon at the and of the string
print "Enter a value: "
in fib.p

I wasnt able to identify what kind of fix can be applied to pawn complier itself.

ARM assembler core not work in Thumb mode (gcc)

Hello!

I try to use amxexec_thumb2_gas.s with AMX_TOKENTHREADING option

In macro NEXT your switch to next instruction processing by load pc
ldr pc, [r14, r11, LSL #2]

Value extracted from amx_opcodelist table:

    .word   .OP_NOP
    .word   .OP_LOAD_PRI
    .word   .OP_LOAD_ALT

But values in this table is even, so load this value in PC switch processor in ARM mode instead of Thumb
Solution:

    .word   .OP_NOP + 1
    .word   .OP_LOAD_PRI + 1
    .word   .OP_LOAD_ALT + 1

Warning on array initializers with explicit tag

Using Pawncc 4.0.4733 compiling attached script gives following warning output, 
although tag for fields .key and .value are correctly set:

array.p(5) : warning 213: tag mismatch
array.p(5) : warning 213: tag mismatch
array.p(6) : warning 213: tag mismatch
array.p(6) : warning 213: tag mismatch
array.p(7) : warning 213: tag mismatch
array.p(7) : warning 213: tag mismatch
array.p(8) : warning 213: tag mismatch
array.p(8) : warning 213: tag mismatch
array.p(9) : warning 213: tag mismatch
array.p(9) : warning 213: tag mismatch

Original issue reported on code.google.com by [email protected] on 17 Jul 2012 at 8:22

Attachments:

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.