Giter Site home page Giter Site logo

iniparser's Introduction

pipeline status latest release

Iniparser 4

Changes in May 2024: We moved to iniparser/iniparser! Go there for:

Changes in March 2024: @lmoellendorf took over maintenance for this project.

  • The objective was to get all known issues fixed and released as v4.2.
  • After that, this project has been frozen on Github as v4.2.1 and
  • development should continue as v5, probably on gitlab.
  • Pointers have been updated.

Thanks a million times to Lars for his tremendous work and help in keeping this library alive!

Many thanks to @touilleman for his exceptional contributions and efforts for maintaining this project for a decade. Manu, you rock!

I - Overview

This modules offers parsing of ini files from C.

Key features:

  • Small : around 1500 sloc inside 4 files (2 .c and 2 .h)
  • Portable : no dependancies, written in -pedantic C
  • Fully re-entrant : easy to make it thread-safe (just surround library calls by mutex)

II - Building project

This project uses CMake as build system. Use these command at the root or the project to get the static (i.e. libiniparser.a) and shared (i.e. libiniparser.so) libraries compiled:

mkdir build
cd build
cmake ..
make all

There are some CMake option which are OFF by default:

  • BUILD_TESTS
  • BUILD_EXAMPLES

From within build directory execute ccmake .. to see all.

III - Tests

mkdir build
cd build
cmake -DBUILD_TESTS ..
make all

While still in the build project you can run the tests by calling ctest. Test output can be found in build directory under Testing/Temporary/LastTest.log.

IV - Examples

To build the examples:

mkdir build
cd build
cmake -DBUILD_EXAMPLES ..
make all

From the build directory run the examples with:

  • ./iniexample
  • ./iniwrite
  • ./parse ../example/twisted.ini

V - Documentation

Documentation is build by default and can be found in build directory under html.

Open the file html/index.html with any HTML-capable browser.

Or see the complete documentation in online.

VI - License

This software is released under MIT License. See LICENSE for more details

VII - Versions

latest release

  • Since v4.2.x Semantic Versioning is applied.
  • Version 4.0 introduced breaking changes in the api.
  • Older versions 3.1 and 3.2 with the legacy api are available as tags.

VIII - FAQ

See FAQ-en.md in this directory for answers to Frequently Asked Questions.

还有简化**翻译在FAQ-zhcn.md.

iniparser's People

Contributors

ahippo avatar ashamedbit avatar barbeque avatar bostjan avatar dbungert avatar delusionallogic avatar dobragab avatar dofuuz avatar dota17 avatar eworm-de avatar foxtacles avatar hramrach avatar jl2210 avatar kdienes avatar lantaris avatar lmoellendorf avatar marhry avatar mbrossard avatar ndevilla avatar nicolas314 avatar noelpower avatar pizhenwei avatar stevebeattie avatar stoeckmann avatar thelostpeace avatar timgates42 avatar touilleman avatar xsquared avatar xteixeira avatar zrrto 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  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

iniparser's Issues

Makefile: target "libiniparser.so" producing file libiniparser.so.0, actually

Hi!

The current Makefile has a target libiniparser.so that actually produces libiniparser.so.0, rather than libiniparser.so:

libiniparser.so:    $(OBJS)
    $(QUIET_LINK)$(SHLD) $(LDSHFLAGS) $(LDFLAGS) -o [email protected] $(OBJS) \
        -Wl,-soname=`basename $@`.0

If that mismatch is intended, a line .PHONY: libiniparser.so is missing to tell make about it.
If not, please use libiniparser.so.0 or even libiniparser.so.$(SONAME_CURRENT) for a target name, instead. Thanks!

Best, Sebastian

function for getting list of sections

I couldnt find this feature, I dont now the section names, and first want to get a list of all sections

I then can get the details of each of those sections, using this list.

Out of bound copy in _strdup()

static char * _strdup(const char s)
{
char * copy = (char
) malloc(strlen(s));
strcpy(copy, s);
return copy ;
}

should be replaced with
char * copy = (char*) malloc(strlen(s)+1);

To avoid out of bound access, since strcpy add the '\0' add the end of the string.

iniparser_getint & iniparser_getdouble should check the return value of strtol and strtod

I propose to rewrite iniparser_getint and iniparser_getdouble functions as follows:

int iniparser_getint(dictionary * d, const char * key, int notfound)
{
char * str ;
char * endptr;
long val;

str = iniparser_getstring(d, key, INI_INVALID_KEY);
if (str==INI_INVALID_KEY) return notfound ;

errno = 0;    /* To distinguish success/failure after call */
val = strtol(str, &endptr, 0);

/* An error occured or no digits were found */
if (errno != 0 || endptr == str)
           return notfound;

return (int)val;

}

double iniparser_getdouble(dictionary * d, const char * key, double notfound)
{
char * str ;
char * endptr;
double val;

str = iniparser_getstring(d, key, INI_INVALID_KEY);
if (str==INI_INVALID_KEY) return notfound ;

errno = 0;    /* To distinguish success/failure after call */
val = strtod(str, &endptr);

/* An error occured or no digits were found */
if (errno != 0 || endptr == str)
           return notfound;

return val;

}

Furthermore, CFLAGS in Makefile should contain -DREENTRANT flag.

Allow file without section

Hi,
I wonder if it's possible to add this options?
Because I want to parse an existing file which do not have section.

reverse if test in strwlc()

static const char * strlwc(const char * in, char *out, unsigned len)
{
    ...
    while ( in[i] != '\0' && i < len-1) {
        out[i] = (char)tolower((int)in[i]);
        i++ ;
    }
    ...
}

Test on i value should be done before being used :
while ( i < len - 1 && in[i] != '\0')

Memory leak with iniparser_getseckeys()

Hello,

I believe there is a memory leak if you use the function iniparser_getseckeys(). The function description correctly states that none of the actual keys should be free()d, but the char ** reference itself is malloc()ed and never free()d within the library. Please let me know if I am mistaken. I came across this when running valgrind on my application that uses iniparser.

Thank you for such a great tool!

Best,
Mike Foss

Error if file doesn't end on a blank line

I'm trying to parse a file with 2 lines:

blabla1 = 4
blabla = 3

And I get this error

iniparser: input line too long in ast.config (2)

If I add an empty line after those 2 lines everything works fine

Making the library thread-safe

I have been using iniparser for a project I am working on, and it is working great. However, I ran into a segmentation fault recently and discovered that the library as written is not thread-safe. The functions strlwc() and strstrip() in iniparser.c are the culprits as they are not re-entrant (as indicated in the comments).

I think that the library documentation should be revised to indicate that it is not currently thread-safe.

However, I have also revised the above functions to take additional arguments that do make them thread-safe. The changes to the rest of the library are transparent to the user. I can send you a patch if you would like.

Best,
Mike Foss

Please add some 'const' annotations

Some API functions are difficulty to use because they require char * arguments although char const * would suffice. E.g.

void foo(char const *sec)
{
    iniparser_getsecnkeys(dict, sec);
}

causes an error due pointer type mismatch.

I suggest to change

-char * iniparser_getsecname(dictionary * d, int n);
+char const * iniparser_getsecname(dictionary * d, int n);

-void iniparser_dumpsection_ini(dictionary * d, char * s, FILE * f);
+void iniparser_dumpsection_ini(dictionary * d, char const * s, FILE * f);

-int iniparser_getsecnkeys(dictionary * d, char * s);
+int iniparser_getsecnkeys(dictionary * d, char const * s);

-char ** iniparser_getseckeys(dictionary * d, char * s);
+char const * const * iniparser_getseckeys(dictionary * d, char const * s);

-char * iniparser_getstring(dictionary * d, const char * key, char * def);
+char const * iniparser_getstring(dictionary * d, const char * key, char const * def);

Changing the return type can break API but it makes it much clear that the return value must not be modified. In case of iniparser_getstring() it is required to propagate the constness of def.

Bug in error handling

I recently found a bug in error handling of iniparser_load. Look at Line 732 of iniparser.c! That break jumps out of the switch, not the while loop processing the lines. errs is set, but processing will go on, errs will be overwritten if a following line is syntactically correct, so the returned dictionary won't be NULL.

Currently there is no way that the programmer could detect the syntax error, only the user can (stderr). Look at Commit 8ffcea6 pointing that out.

I didn't create a pull request for this as I don't know what error handling strategies would I follow.

  1. Stop at first syntax error, free everything and return NULL.
  2. Detect and print all syntax errors, free everything and return NULL.
  3. Print syntax error, but return a valid dictionary.

The current implementation varies between 2 and 3. If there was a valid Section or Value line after syntax error, it's 3, otherwise 2.

I provided a fix resulting in 1 (e786132), but that's just ugly. Bad thing is, the breaks are chaotic in iniparser_load. I can rewrite it using goto instead of random breaks, either implementing strategy 1 or 2, like this, if necessary.

It is your job to decide the strategy, feel free to cherry-pick these commits if you want strategy 1.


There is another huge problem in iniparser_load about error handling: it writes the message to stderr. This is just fine for CLI programs written in C, but consider the following:

  • GUI applications that have stderr omitted, and would like show the message to the user.
  • C++ wrapper for iniparser. In C++ it is usually better to throw something derived from std::runtime_error containing the message instead of arbitarily printing to stdout.

So most C libraries have const char * getlasterror() to handle the problem, and this gives a workaround for both problems. You can see my approach: 83c45bf

Note that this isn't perfect either. For example it contains possibility of buffer overflows, that could be solved by snprintf. Bad news: snprintf is not part of the C89 standard, and only the latest MSVC compilers have the C99 compatible version...

This change has only a small impact on the API, so it can be changed without breaking code based on iniparser. More bad news: CLI programs might expect that iniparser writes the errors to stderr.

A possible solution: logging both into stderr and ERRORBUFFER by default, and adding void iniparser_stderr(int enabled) function that would toggle printing to stderr.

This is another question that You should decide.

dobragab

Variable substitution

Hi,

Could it be possible to add 'variable substitution' for the INI syntax?
Example:

[main]
firstname=MyFirstName
lastname=MyLastName
fullname=${firstname}_${lastname} 
regex=foo.*${fullname}\s+bar\w+baz

The ${} idea comes from 'sh' syntax.
Another could be %()s like Python's ConfigParser syntax.

This is more of a "feature request" than "issue", I guess. :)

Thanks & Regards,
Shantanu

value following quoted string are skipped

Given the .ini

[main]
key = "hello" world

Iniparser will stop reading after the first double quoted string so we will end up with
key=hello instead of key=hello world

I'm not sure if it's a bug or an "undocumented feature" (a line should not contain more than a single quoted string) but in such case we should display a syntax error instead of just dropping information

create tags

would be nice to have git tags on released versions for easier movement in source tree … O:-)

Makefile: Please bump soname version from 0 to 1

Hi!

Comparing headers of iniparser 3.x and 4.x they do not seem to be ABI compatible. I would therefore ask to bump the soname version from 0 to 1 to reflect that incompatibility at filename level, properly. Thanks!

Best, Sebastian

Memory Corruption

Hello there,
I was programming on a small C++ project and was using this library in version 4.0-1. At some point I added more data to the ini and suddenly my programm crashed at iniparser_load(); with the messages "free(): invalid next size(fast)" and "malloc(): heap corruption...". I ran my program through valgrind and there was no error up until iniparser_load() got invoked.

So that leads me to believe it's an issue with the library.

So anyway, just a minimal working example which only uses that single function already create a heap of error in valgrind:

==11889== Invalid write of size 8
==11889==    at 0x4C2ECB3: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11889==    by 0x4E37E75: iniparser_load (in /usr/lib/libiniparser.so.0)
==11889==    by 0x4006DE: main (in /home/pfannkuchen/cpp/stuff/initest/test)
==11889==  Address 0x53ddde8 is 8 bytes inside a block of size 15 alloc'd
==11889==    at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11889==    by 0x4E37E62: iniparser_load (in /usr/lib/libiniparser.so.0)
==11889==    by 0x4006DE: main (in /home/pfannkuchen/cpp/stuff/initest/test)
==11889== 
==11889== Invalid read of size 1
==11889==    at 0x4C2D524: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11889==    by 0x4E37532: strstrip (in /usr/lib/libiniparser.so.0)
==11889==    by 0x4E37E7D: iniparser_load (in /usr/lib/libiniparser.so.0)
==11889==    by 0x4006DE: main (in /home/pfannkuchen/cpp/stuff/initest/test)
==11889==  Address 0x53dddef is 0 bytes after a block of size 15 alloc'd
==11889==    at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11889==    by 0x4E37E62: iniparser_load (in /usr/lib/libiniparser.so.0)
==11889==    by 0x4006DE: main (in /home/pfannkuchen/cpp/stuff/initest/test)
==11889== 
==11889== Invalid write of size 1
==11889==    at 0x4E37585: strstrip (in /usr/lib/libiniparser.so.0)
==11889==    by 0x4E37E7D: iniparser_load (in /usr/lib/libiniparser.so.0)
==11889==    by 0x4006DE: main (in /home/pfannkuchen/cpp/stuff/initest/test)
==11889==  Address 0x53dddef is 0 bytes after a block of size 15 alloc'd
==11889==    at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11889==    by 0x4E37E62: iniparser_load (in /usr/lib/libiniparser.so.0)
==11889==    by 0x4006DE: main (in /home/pfannkuchen/cpp/stuff/initest/test)
==11889== 
==11889== Invalid read of size 1
==11889==    at 0x4C30E34: rawmemchr (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11889==    by 0x50B12B1: _IO_str_init_static_internal (in /usr/lib/libc-2.21.so)
==11889==    by 0x50A5F26: vsscanf (in /usr/lib/libc-2.21.so)
==11889==    by 0x50A0A66: sscanf (in /usr/lib/libc-2.21.so)
==11889==    by 0x4E3803D: iniparser_load (in /usr/lib/libiniparser.so.0)
==11889==    by 0x4006DE: main (in /home/pfannkuchen/cpp/stuff/initest/test)
==11889==  Address 0x53dddef is 0 bytes after a block of size 15 alloc'd
==11889==    at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11889==    by 0x4E37E62: iniparser_load (in /usr/lib/libiniparser.so.0)
==11889==    by 0x4006DE: main (in /home/pfannkuchen/cpp/stuff/initest/test)
==11889== 
==11889== Invalid write of size 2
==11889==    at 0x4C2ECFB: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11889==    by 0x4E37E75: iniparser_load (in /usr/lib/libiniparser.so.0)
==11889==    by 0x4006DE: main (in /home/pfannkuchen/cpp/stuff/initest/test)
==11889==  Address 0x53ddf92 is 18 bytes inside a block of size 19 alloc'd
==11889==    at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11889==    by 0x4E37E62: iniparser_load (in /usr/lib/libiniparser.so.0)
==11889==    by 0x4006DE: main (in /home/pfannkuchen/cpp/stuff/initest/test)
...
==11889== ERROR SUMMARY: 103 errors from 6 contexts (suppressed: 0 from 0)

Please remove `xstrdup()` from public API

dictionary.h provides an xstrdup() function. This function name is very generic and it is very likely that a project wants to implement an own xstrdup() function.

I suggest to change its name to something like iniparser_xstrdup() to avoid such conflicts.

Static library: Makefile bug

Hi there,

I believe there's a small bug in the Makefile that causes it to incorrectly build the static library. On the command line, only the first depency is included, causing it to miss the dictionary.o file. Quick fix below, which only changes $< to $^:

diff --git Makefile Makefile
index 8877377..588574a 100644
--- Makefile
+++ Makefile
@@ -48,7 +48,7 @@ OBJS = $(SRCS:.c=.o)
 default:       libiniparser.a libiniparser.so

 libiniparser.a:        $(OBJS)
-       $(QUIET_AR)$(AR) $(ARFLAGS) $@ $<
+       $(QUIET_AR)$(AR) $(ARFLAGS) $@ $^
        $(QUIET_RANLIB)$(RANLIB) $@

 libiniparser.so:       $(OBJS)

Can't compile on Windows

I wanted to try the INI parser in a Windows application.
But compiling it was not possible, as the include file unistd.h could not be found (used in your include file dictionary.h).
So the parser is not really portable yet.

support dots in key and UTF8 text

I have a problem that the keys are not allowed to have dots e.g. "10.123=example".
Moreover UTF8 files cannot be read e.g. a string value "10.123="Grüzi"

what is the hash use for?

Hi, I have some doubt about this project, Does hash is useless in this project?I thought hash is to allocate the key position,but I found this project just use to compare and still compare the key value? is it necessarily or we just only need to compare the key, why need compare the hash value? hoop for your reply,best regards!

iniparser_set not working for key

Hi,

I have a ini file as following:

[test]

Now I try to create a new key using iniparser_set function:

int set = iniparser_set(ini, "test:key1", "test_key");

The new key "key1" is not added in ini file. The value of variable "set" is 0.

It also doesnt work if the key "test_key" exist in ini file.

Buffer overflow section+key

https://github.com/ndevilla/iniparser/blob/master/src/iniparser.c#L702

If section and key together have a length which is greater than ASCIILINESZ-1, this is a buffer overflow. That also means that the actual length of a section name or key is limited to less than the advertised ASCIILINESZ.

To fix this, the tmp buffer should have a size of (ASCIILINESZ*2)+1. Same thing for the buffer in strlwc. I don't think the ':' needs to be taken into account, as a section name can't actually have a length of more than ASCIILINESZ - 2 due to the brackets

Minor warning on MSVC with warning level 4.

This is a very minor issue. When compiling dictionary.c on MSVC with the highest warning level, on line 123 it complains about assignment within a conditional. A simple fix to this will have it compile cleanly on /W4 and make purists happy (like me).

Parsing surprise for values inside of tick or quote marks

When a value is inside of a tick mark or a quote mark, and there is a leading or trailing space inside of the enclosing marks, the user is most likely to expect the leading or trailing space to stay attached to the value until the application consuming the iniparser library receives the value.

Instead, lines 581 -> 595 will uniformly strip leading and trailing spaces from values inside of quote/tick marks.

A possible way to resolve this is:

else if(sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2
     || sscanf (line, "%[^=] = '%[^\']'",   key, value) == 2)
{
    /* Usual key=value inside of tickmarks or quote marks, with or without comments */
    strcpy(key, strstrip(key));
    strcpy(key, strlwc(key));
    //Don't want to strstrip the value, because the user put a space inside the ticks delibrately.
    //strcpy(value, strstrip(value));
    /*
     * sscanf cannot handle '' or "" as empty values
     * this is done here
     */
    if (!strcmp(value, "\"\"") || (!strcmp(value, "''")))
    {
        value[0]=0 ;
    }
    sta = LINE_VALUE ;
}
else if(sscanf (line, "%[^=] = %[^;#]",     key, value) == 2)
{
    /* Usual key=value inside of tickmarks or quote marks, with or without comments */
    strcpy(key, strstrip(key));
    strcpy(key, strlwc(key));
    strcpy(value, strstrip(value));

    sta = LINE_VALUE ;
}

Compile the project on STM32 microcontroller with IAR

Hello

I want to use this library on STM32 microcontroller compiler with IAR.
Has anyone ever performed this operation?

I already encounter problems. especially :

  • #include <unistd.h> I do not call posix on stm32.
  • ssize_t This type does not correspond to anything.

Thanks for your help

gcc format-overflow warning

Hello, I'm getting a warning when compiling with gcc 8.1.0:

iniparser/iniparser.c: In function 'iniparser_load':
iniparser/iniparser.c:791:32: warning: 'sprintf' may write a terminating nul past the end of the destination [-Wformat-overflow=]
             sprintf(tmp, "%s:%s", section, key);
                                ^
iniparser/iniparser.c:791:13: note: 'sprintf' output between 2 and 2050 bytes into a destination of size 2049
             sprintf(tmp, "%s:%s", section, key);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The variables size are:

    char section [ASCIILINESZ+1] ;
    char key     [ASCIILINESZ+1] ;
    char tmp     [(ASCIILINESZ * 2) + 1] ;

With:

#define ASCIILINESZ         (1024)

The tmp size should be one more byte because the string is "%s:%s", I guess the ':' character was not taken into account.

fprintf function is too slow when save something to file

In iniparser_dump_ini() and iniparser_dumpsection_ini(), the author uses fprintf to save ini data to file. When I use those functions ,I found it took me 7~8 seconds every time to save all info to a file. My embedded platform is MIPS and OS is Nuttx. After a long period of debugging, I used sprintf and fwrite to replace fprintf. Then it only took me 1 second to save completely. So I feel that I have the duty to report this .

在函数 iniparser_dump_ini() 和 iniparser_dumpsection_ini() 中,作者使用fprintf函数来保存数据到文件。当我用libiniparse库的时候,我发现每次将数据保存到文件都需要5~6秒。我的平台是MIPS,系统是Nuttx。经过一段时间的调试,我用sprintf来格式化数据,然后用fwrite将数据写入文件,这种方式只需要不到1秒钟的时间。我感觉我有责任来报告一下这个问题。

Enable strict parsing

Enable more thorough check of parsing overflows and errors.
It will check for trailing junk characters in number strings.
Whitespace characters are allowed (isspace()), anything else will result in a parsing error.

Pull request across different sites doesn't work with GitHub.
My cloned repo is on BitBucket.
Here are some changes in patch file format.

0001-Add-more-thorough-number-parsing-checks.-Fix-a-coupl.txt

Invalid out of bounds stack memory read on some inputs in function iniparser_load()

An out of bounds stack read access can happen in the function iniparser_load(). This can be triggered by parsing a file that simply contains a zero-byte (create with e.g. "dd if=/dev/zero of=zerobytefile bs=1 count=1"). To see this you can use address sanitizer (add -fsanitize=address in CFLAGS).

This is the code causing this:

    while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) {
        lineno++ ;
        len = (int)strlen(line)-1;
        if (len==0)
            continue;
        /* Safety check against buffer overflows */
        if (line[len]!='\n' && !feof(in)) {

The problem here is that when the line consists of a zero byte then strlen(line) is 0 and len becomes -1. Therefore line[-1] is read and that is invalid memory.

This could be fixed by changing the check for len to <=0, but I'm not sure this is a good solution (this only works because len is signed, it probably should be unsigned anyway).

This issue was found with the tool american fuzzy lop. Here's the error message from address sanitizer:

==1691==ERROR: AddressSanitizer: stack-buffer-underflow on address 0x7ffceaee49ff at pc 0x0000004e5486 bp 0x7ffceaee49d0 sp 0x7ffceaee49c8
READ of size 1 at 0x7ffceaee49ff thread T0
    #0 0x4e5485 in iniparser_load /f/iniparser/iniparser/src/iniparser.c:684:13
    #1 0x4df09a in main /f/iniparser/iniparser/example/parse.c:19:11
    #2 0x7f938881a7af in __libc_start_main (/lib64/libc.so.6+0x207af)
    #3 0x417e38 in _start (/mnt/ram/iniparser/parse+0x417e38)

Address 0x7ffceaee49ff is located in stack of thread T0 at offset 31 in frame
    #0 0x4e318f in iniparser_load /f/iniparser/iniparser/src/iniparser.c:645

  This frame has 5 object(s):
    [32, 1057) 'line' <== Memory access at offset 31 underflows this variable
    [1200, 2225) 'section'
    [2368, 3393) 'key'
    [3536, 5585) 'tmp'
    [5728, 6753) 'val'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-underflow /f/iniparser/iniparser/src/iniparser.c:684:13 in iniparser_load
Shadow bytes around the buggy address:
  0x10001d5d48e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10001d5d48f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10001d5d4900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10001d5d4910: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10001d5d4920: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10001d5d4930: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1[f1]
  0x10001d5d4940: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10001d5d4950: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10001d5d4960: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10001d5d4970: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10001d5d4980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==1691==ABORTING

fix for compiler warning:

 src/iniparser.c:244:5: warning: implicit declaration of function ‘snprintf’    [-Wimplicit-function-declaration]
     snprintf(keym, secsize, "%s:", s);

If snprintf is used:

   -CFLAGS  += -fPIC -Wall -ansi -pedantic
   +CFLAGS  += -fPIC -Wall -std=c99 -pedantic

Would you accept patches moving to Autotools?

Hi!

I noticed that the iniparser maintainer in Gentoo wrote a simple autotools build system for iniparser to apply that as a patch, see https://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/dev-libs/iniparser/files/iniparser-3.0-autotools.patch?view=markup .

I'd be happy to port that to iniparser 4.0 as a pull request for you if there is any chance to have it accepted, in general. Personally, I would consider that a good move. What do you think?

Best, Sebastian

Add a FAQ to the README

I'm thinking about a copy-paste of the last discussed issue:

FAQ

Is Iniparser thread safe ?

Starting from version 4, iniparser is designed to be thread-safe, provided you surround it with your own mutex logic.
The choice not to add thread safety inside the library has been done to provide more freedom for the developer, especially when dealing with it own custom reading logic (i.g. acquiring the mutex, reading plenty of entries in iniparser, then releasing the mutex).

Your build system isn't portable, let me help you...

I have received countless contributions from distrib people to modify the Makefile into what they think is the "standard", which I had to reject.
The default, standard Makefile for Debian bears absolutely no relationship with the one from SuSE or RedHat and there is no possible way to merge them all.
A build system is something so specific to each environment that it is completely pointless to try and push anything that claims to be standard. The provided Makefile in this project is purely here to have something to play with quickly.

@ndevilla Do you see any other point to talk about ?

dependancy issue

make example can not gen a new execute file when the files of src directory are modified.

iniparser_dump_ini() does not protect values when writing back to INI file.

Problem is when iniparser_dump_ini() function is called, it will save values without enclosing them with '' or "" marks even if in original file had them around values.

This will cause that if data has ; or # characters they will be sanitized away in next load.

I wrote test case to demonstrate the issue -> https://github.com/JaniPajarinen/iniparser/tree/save_load_test

And fix -> https://github.com/JaniPajarinen/iniparser/tree/save_load_fix

Multiline value with comment

Hello,

I just noticed that this multine value:

pizza=yes \
    no \
    maybe \ ; comment for this line only
    i dont know

will result in this after being parsed:

yes no maybe \

It will ignore the last line i dont know because of the comment in the previous line. Also the \ at the end of the line will be part of the parsed value.

Is this this behaviour expected when adding comments to multine values?

Makefile: Please drop adding -O2/-g to CFLAGS or make it optional

Hi!

Right now, the Makefile appends either -O2 or -g:

ifndef DEBUG
CFLAGS += -O2
else
CFLAGS  += -g
endif

It would be cool if you could support a away to have neither happen since it takes away control from the user who may want -Os but none of these, for example. Any chance?
Thank you!

Best, Sebastian

Support for duplication Sections/Keys

Hi,

I have a file seems like:

[Section]
  Key = value1
  Key = value2

Currently iniparser loads only last value. I suggest to load it as list, like:

[Section:Key]=[value1;value2]

Another solution, append non-unique Keys with index value and extend API to inform how many keys with given name is present:

[Section:Key:0]=[value1]
[Section:Key:1]=[value2]
or (to avoid conflict with real names)
[Section:Key][0]=[value1]
[Section:Key][1]=[value2]

and

// key: section:key
int iniparser_getnkeys(const dictionary * dict, const char * key);

usage:

int n1 = iniparser_getnkeys(dict, "Section:Key");
// n1 == 2 

after that key definition can be extended like:

section:key[index]

Access without index pointing should be refer to zero element. Also, it will be good, that zero element will be accessible for unique keys too.

Provide a conanical header installation path

Upstream iniparser does not provide a 'make install' support. Downstream distributions may install the header files to different places.
For example, Ubuntu installs header files to /usr/include/iniparser but Fedora installs them to /usr/include directly.
It would hard for distributions to negotiate with each other to decide a common path. It's better for upstream to make this decision.

iniparse_set

My code like:
directory* dic;
iniparse_load("inipath");
ret = iniparse_set(ini, "sec", "");
ret = iniparse_set(ini, "sec:key", "value");

My problem is :
ret is always 0, but the ini file still empty

Please avoid using sscanf as it is not portable

Hi,

The iniparser library is making use of the sscanf function. This function is not portable in the sense that it is locale dependant. This function behaves for example different on an english computer compared with running it on a korean computer.

Is there any chance to get rid of it?

Thanks in advance!

Best regards,
sconstanter

Empty string with quotes.

for example:
filter = ""

this code can't handle it

} else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2
       ||  sscanf (line, "%[^=] = '%[^\']'",   key, value) == 2) {

this string will be processed in

} else if (sscanf (line, "%[^=] = %[^;#]", key, value) == 2) {

the condition

if (!strcmp(value, "\"\"") || (!strcmp(value, "''"))) {
        value[0]=0 ;
}

will not be processed.

result:
load = ""
save = """"
load = """"
save = """"""
etc.

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.