b4n left a comment (geany/geany#4303)

Yeah, the issue is that the columns are just wrong, and `mio_new_mio()` gets 
several things wrong in these cases.  With `mini-geany` I get another issue 
(that the C library allows seeking off-bounds, and the rest of the code doesn't 
do enough checking until the `mio_read()` can't read enough and the calling 
code doesn't properly handle the error), but it's the same underlying problem.

So yeah I agree that the code around there need hardening not to crash, and the 
actual issue of incorrect offsets need fixing for proper results.  I'll see if 
I can figure something out, but I won't be able tonight I think.

<details>
<summary>FWIW, here's a couple tests I made in uctags</summary>

```diff
diff --git a/main/mini-geany.c b/main/mini-geany.c
index e02b3c19a..06d2f8be6 100644
--- a/main/mini-geany.c
+++ b/main/mini-geany.c
@@ -370,7 +370,7 @@ extern int main (int argc, char **argv)
                {
                        printf("\nParsing %s:\n", argv[i]);
                        /* parseRawBuffer() is called repeatadly during Geany 
execution */
-                       parseRawBuffer(argv[i], NULL, 0, getNamedLanguage("C", 
0), tagArray);
+                       parseRawBuffer(argv[i], NULL, 0, 
getNamedLanguage("PHP", 0), tagArray);
 
                        processCollectedTags(tagArray);
                }
diff --git a/main/mio.c b/main/mio.c
index baabcf5bf..5ef70f5a0 100644
--- a/main/mio.c
+++ b/main/mio.c
@@ -317,6 +317,9 @@ MIO *mio_new_mio (MIO *base, long start, long size)
        MIO *submio;
        size_t r;
 
+       fprintf(stderr, "mio_new_mio(%p, %ld, %ld): called on a base of type 
%d\n",
+               (void*) base, start, size, base->type);
+
        original_pos = mio_tell (base);
 
        if (size == -1)
@@ -324,25 +327,41 @@ MIO *mio_new_mio (MIO *base, long start, long size)
                long end;
 
                if (mio_seek (base, 0, SEEK_END) != 0)
+               {
+                       fprintf(stderr, "mio_new_mio(%p, %ld, %ld): cannot seek 
to end (errno=%d)\n",
+                               (void*) base, start, size, errno);
                        return NULL;
+               }
                end = mio_tell (base);
                Assert (end >= start);
                size = end - start;
        }
 
        if (mio_seek (base, start, SEEK_SET) != 0)
+       {
+               fprintf(stderr, "mio_new_mio(%p, %ld, %ld): cannot seek to 
offset %ld (errno=%d)\n",
+                       (void*) base, start, size, start, errno);
                return NULL;
+       }
 
        data = xMalloc (size, unsigned char);
        r= mio_read (base, data, 1, size);
        mio_seek (base, original_pos, SEEK_SET);
 
        if (r != size)
+       {
+               fprintf(stderr, "mio_new_mio(%p, %ld, %ld): cannot read %ld 
bytes, got only %lu (errno=%d)\n",
+                       (void*) base, start, size, size, r, errno);
                goto cleanup;
+       }
 
        submio = mio_new_memory (data, size, eRealloc, eFreeNoNullCheck);
        if (! submio)
+       {
+               fprintf(stderr, "mio_new_mio(%p, %ld, %ld): mio_new_memory(%p, 
%lu, eRealloc, eFreeNoNullCheck) failed (errno=%d)\n",
+                       (void*) base, start, size, (void*) data, size, errno);
                goto cleanup;
+       }
 
        return submio;
 
diff --git a/main/read.c b/main/read.c
index 2118ec1e9..79f3d5754 100644
--- a/main/read.c
+++ b/main/read.c
@@ -1453,7 +1453,7 @@ extern void   pushArea (
        size_t size = q - p;
        subio = mio_new_mio (File.mio, p, size);
        if (subio == NULL)
-               error (FATAL, "memory for mio may be exhausted");
+               error (FATAL, "failed to create mio of substream <%ld, %ld> 
(length=%zu): memory may be exhausted?", p, q, size);
 
        runModifiers (promise,
                                  startLine, startColumn,
```

```console
$ gdb --nx --batch -ex run -ex 'bt full' --args ./mini-geany 
../geany/tests/ctags/wp-guest.php
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
This parser only parses C files - provide them as arguments on the command line 
or get a hard-coded buffer parsed when no arguments are provided


Parsing ../geany/tests/ctags/wp-guest.php:
mio_new_mio(0x555555c018c0, 0, 0): called on a base of type 0
mio_new_mio(0x555555c018c0, 22, 94): called on a base of type 0
mio_new_mio(0x555555c018c0, 141, 2): called on a base of type 0
mio_new_mio(0x555555c018c0, 169, 18): called on a base of type 0
mio_new_mio(0x555555c018c0, 220, 84): called on a base of type 0
mio_new_mio(0x555555c018c0, 329, 22): called on a base of type 0
mio_new_mio(0x555555c018c0, 405, 216): called on a base of type 0
mio_new_mio(0x555555c018c0, 684, 49): called on a base of type 0
mio_new_mio(0x555555c018c0, 751, 56): called on a base of type 0
mio_new_mio(0x555555c018c0, 831, 17): called on a base of type 0
mio_new_mio(0x555555c018c0, 869, 49): called on a base of type 0
mio_new_mio(0x555555c018c0, 956, 87): called on a base of type 0
mio_new_mio(0x555555c018c0, 1104, 28): called on a base of type 0
mio_new_mio(0x555555c018c0, 1156, 7): called on a base of type 0
mio_new_mio(0x555555c018c0, 1217, 8): called on a base of type 0
mio_new_mio(0x555555c018c0, 1240, 6): called on a base of type 0
mio_new_mio(0x555555c018c0, 1337, 34): called on a base of type 0
mio_new_mio(0x555555c018c0, 1394, 20): called on a base of type 0
mio_new_mio(0x555555c018c0, 1479, 4): called on a base of type 0
mio_new_mio(0x555555c018c0, 1505, 59): called on a base of type 0
mio_new_mio(0x555555c018c0, 1505, 59): cannot read 59 bytes, got only 2 
(errno=0)
Error: failed to create mio of substream <1505, 1564> (length=59): memory may 
be exhausted?

Program received signal SIGSEGV, Segmentation fault.
0x00005555556cb542 in mio_memory_get_data (mio=mio@entry=0x0, 
size=size@entry=0x0) at main/mio.c:429
429             if (mio->type == MIO_TYPE_MEMORY)
#0  0x00005555556cb542 in mio_memory_get_data (mio=mio@entry=0x0, 
size=size@entry=0x0) at main/mio.c:429
        ptr = 0x0
#1  0x00005555555adb96 in pushArea (useMemoryStreamInput=<optimized out>, 
startLine=startLine@entry=57, startColumn=startColumn@entry=22, 
endLine=endLine@entry=57, endColumn=endColumn@entry=81, 
sourceLineOffset=sourceLineOffset@entry=57, promise=19) at main/read.c:1460
        p = 1505
        q = <optimized out>
        original = {type = MIO_TYPE_FILE, tag = 0x555555c018c0, impl = {file = 
{__pos = 1483, __state = {__count = 0, __value = {__wch = 0, __wchb = 
"\000\000\000"}}}, mem = 1483}}
        tmp = {type = MIO_TYPE_FILE, tag = 0x555555c018c0, impl = {file = 
{__pos = 1483, __state = {__count = 0, __value = {__wch = 0, __wchb = 
"\000\000\000"}}}, mem = 1483}}
        subio = <optimized out>
        __func__ = "pushArea"
        size = 59
#2  0x00005555555a96a9 in runParserInArea (language=55, startLine=57, 
startCharOffset=22, endLine=57, endCharOffset=81, sourceLineOffset=57, 
promise=19) at main/parse.c:4341
        tagFileResized = <optimized out>
#3  0x00005555555aaa94 in forcePromises () at main/promise.c:197
        p = 0x555555c13380
        i = 19
        tagFileResized = false
#4  0x00005555555a9774 in createTagsWithFallback (failureInOpenning=<synthetic 
pointer>, mtime=0, mio=0x0, language=89, fileName=0x7fffffffe119 
"../geany/tests/ctags/wp-guest.php") at main/parse.c:4370
        exclusive_subparser = -2
        tagFileResized = false
        exclusive_subparser = <optimized out>
        tagFileResized = <optimized out>
        __func__ = "createTagsWithFallback"
#5  parseMio (fileName=0x7fffffffe119 "../geany/tests/ctags/wp-guest.php", 
language=89, mio=mio@entry=0x0, mtime=mtime@entry=0, 
useSourceFileTagPath=useSourceFileTagPath@entry=false, 
clientData=clientData@entry=0x555555c0cab0) at main/parse.c:4530
        tagFileResized = false
        failureInOpenning = false
#6  0x00005555555a9b56 in parseRawBuffer (fileName=<optimized out>, 
buffer=buffer@entry=0x0, bufferSize=bufferSize@entry=0, language=<optimized 
out>, clientData=clientData@entry=0x555555c0cab0) at main/parse.c:4602
        mio = 0x0
        r = <optimized out>
#7  0x00005555555869cd in main (argc=2, argv=<optimized out>) at 
main/mini-geany.c:373
        i = <optimized out>
        tagArray = 0x555555c0cab0
$ tail -c+1505 ../geany/tests/ctags/wp-guest.php
>
```

-- 
Reply to this email directly or view it on GitHub:
https://github.com/geany/geany/pull/4303#issuecomment-2927839571
You are receiving this because you are subscribed to this thread.

Message ID: <geany/geany/pull/4303/[email protected]>

Reply via email to