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]>