Hi,

I have been looking at the config parser and i intend to fix it. It
looks like we have to drop the 80 char, dynamically increasing buffer.
I'll try explain why and using getserv* as example but everything here
applies to getproto* and getnet* funcs too.

As I understood, Berhard really wanted allocate 80 chars line buffer
by default and if lines in /etc/services are longer increase the
buffer size dynamically with realloc()[1]. The current git master is
broken with this, and it is *almost* possible to fix it. I'll try
explain the problem.

A too line that is too long, is detected by that there are no '\n'. If
the parser is using a buffer that was allocated by the parser itself,
then it is possible to do realloc from the
bb_get_chunk_with_continuation() function as it does here:
http://git.uclibc.org/uClibc/tree/libc/misc/internals/parse_config.c#n77

However, getserv* functions uses its own allocated buffer so
parser->allocated is not set, and therefore the buffer will not be
extended.

Currently the getservent_r() will always return ERANGE
(http://git.uclibc.org/uClibc/tree/libc/inet/getservice.c#n90)
on any error meaning that if you do getservevent("foo", "bar") you'll
end up with an eternal loop
(http://git.uclibc.org/uClibc/tree/libc/inet/getservice.c#n160)

This can be fixed by letting bb_get_chunk_with_continuation() return
-1 on EOF or -2 if no newline was found, and let config_read() either
0 for EOF, -ERANGE for not enough space for buf or a positive number
for number of seen tokens. This will make getservbyname() and
getservbyport() work. I have patches for this (and also a patch for
fixing the memleak that is currently there)

But...

That will not work for getservent(), since the line that caused the
ERANGE is already read and will be lost. So if you have a line in
/etc/services:

http      80/tcp  # world wide web, and some blablabla .... bla bla
.... line contines past by 80 chars

Then would running getservent() simply skip this line. getservent_r()
would return ERANGE and the loop
http://git.uclibc.org/uClibc/tree/libc/inet/getservice.c#n123 would
just skip it.

So basically, dynamic reallocation will not work for getservent(). If
we at any cost want keep 80 char buf size, then we need do some tricks
with letting config_read() do the allocation if getserv*_r() functions
passed NULL and then somehow prevent config_close() to free it.
I think it just not worth it.

Unless someone have some really strong arguments to keep the 80 char
bufsize, I'll just set static line bufsize to 256 chars and then just
let the config parser only ready the 256 first chars on each line and
ignore the rest.

-- 
Natanael Copa

 [1] http://lists.busybox.net/pipermail/uclibc/2010-August/044270.html
_______________________________________________
uClibc mailing list
uClibc@uclibc.org
http://lists.busybox.net/mailman/listinfo/uclibc

Reply via email to