ini file parser

Build Status

Iniparser 4

I - Overview

This modules offers parsing of ini files from the C level. See a complete documentation in HTML format, from this directory open the file html/index.html with any HTML-capable browser.

Key features :

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

II - Building project

A simple make at the root of the project should be enough to get the static (i.e. libiniparser.a) and shared (i.e. libiniparser.so.0) libraries compiled.

You should consider trying the following rules too :

  • make check : run the unitary tests
  • make example : compile the example, run it with ./example/iniexample

III - License

This software is released under MIT License. See LICENSE for full informations

IV - Versions

Current version is 4.1. Version 4.0 introduces breaking changes in the api. Older versions 3.1 and 3.2 with the legacy api are available as tags.

V - FAQ

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

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

Comments
  • fprintf function is  too slow when save something to file

    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 sprintfand fwriteto 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秒钟的时间。我感觉我有责任来报告一下这个问题。

  • Making the library thread-safe

    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, pull in some more constification of arguments.

    Please, pull in some more constification of arguments.

    This is a part of changeset 24324fe40946f721ae3370f428b6f9a319d60926, you've refused to pull from my previous pull request [1].

    [1] https://github.com/ndevilla/iniparser/pull/9

  • build: migrate build system to autotools

    build: migrate build system to autotools

    Hi,

    I've created proper autotools build environment to support the most common build procedure: ./configure make make check make install

    Motivation: iniparser is a neat library that I integrated into Snoopy Logger. But I had to hackishly add it (copy contents, create custom make rules) which was not elegant. Switching iniparser to autotools-based build system allows anyone to add it to their project with as little hassle as possible, using nested subpackages feature.

    The only trick is to disable shared builds of iniparser, so parent project links itself with static iniparser library instead of dynamic one. For this, the appropriate switch was created (--enable-subpackage, more info below).

    You can see how iniparser is integrated into project that requires it, by means of autotools nested subpackage, here: https://github.com/a2o/snoopy/commit/82a0c81da4742fc48978493007c9b8dc2e42179d

    Please ask if you have further questions about this.

    If possible, please share your opinion about this pull request.

    Here follows the commit message:

    Iniparser is mostly used as a subcomponent of other projects. Some of them required it as shared library that is already present on the target system, while others might want to incorporate it into own package distribution and build/ldadd it to their final binary/ library statically.

    Autotools suite supports a really nice feature called subpackages. It allows project to have subpackage as it's dependency, and does recursive ./configure / make handling by itself.

    With proper autotools support, iniparser can be just dropped into another project, add a few settings to configure.ac, lib/Makefile.am and src/Makefile.am and we are ready to go.

    For this to work (to be embedable statically into another project), another way of building iniparser had to be implemented. It is reachable by the switch --enable-subpackage. This causes main library to be built as noinst (not-installing library), which in turn causes libiniparser to produce only it's static version. This is the desired result, as this causes parent project to link iniparser statically into it's libs/binaries.

    Additionally, an optional --disable-documentation switch was created, as some systems might not have doxygen program installed on them.


    b.

  • Please make 4.0 visible at http://ndevilla.free.fr/iniparser/index.html

    Please make 4.0 visible at http://ndevilla.free.fr/iniparser/index.html

    Maybe even upload the 4.0 tarball up there, too. Right now, for distro package maintainers its very easy to overlook that there are post-3.1 releases. Thanks!

  • Bug in error handling

    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 8ffcea6f516270f84ef7716c983fd2982ecd9b91 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 (e78613270c28891215b2fa2a0b21914e9ee78175), 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: 83c45bf29452b1fdbe4181d2ae9dbb7605b2b7df

    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

  • Memory leak with iniparser_getseckeys()

    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

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

    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
    
  • test_dictionary: fix warning/error when compiling with -O1 or higher

    test_dictionary: fix warning/error when compiling with -O1 or higher

    I build the whole iniparser with -O2 -Wall options. This is the only error that pops out, in test suite. The rest of commit message follows below.


    If test suite is built with -01 or higher, and combined with -Wall, it produces the following error:

    test_dictionary.c: In function ‘get_dump’: test_dictionary.c:131:10: warning: ignoring return value of ‘fread’, declared with attribute warn_unused_result [-Wunused-result] fread(dump_buff, 1, dump_size, fd); ^

    The workaround is to assign return value to dump_size. The value returned by fread() should be equal to original dump_size, unless an error occured. As dump_size is not used after that call, it matters not whether check for error is performed or not, thus it is skipped.

  • Parsing surprise for values inside of tick or quote marks

    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 ;
    }
    
  • Can't compile on Windows

    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.

  • Fix segfault on malformed config files

    Fix segfault on malformed config files

    iniparser_getboolean() can segfault on malformed config files. #125 There are similar problem in iniparser_getlongint() and iniparser_getdouble().

    iniparser_getstring() returns NULL if there are section(not key) with that name.

    The key does not exists, so it's better to return default fallback. And returning NULL for "string" is not likely to be considered by programmers, which can be security problem.

    Fixes #125

  • Superimpose function

    Superimpose function

    I would like to add a function similar to iniparser_load(), but with the ability to overwrite some of the keys in an existing dictionary. This library feature will allow one to work with "global" and "user" settings, widely used in linux programs, where "user" (custom) settings take priority over "global" (system, default) ones.

  • test/testiniparser.c: fix missing comma in token test list

    test/testiniparser.c: fix missing comma in token test list

    Fix missing comma separating two test cases in the Test_iniparser_getboolean() token_true list. Without this, the 'Y' testcase was being skipped.

    (Issue was found by coverity.)

    Signed-off-by: Steve Beattie [email protected] Bug: https://github.com/ndevilla/iniparser/issues/131

  • Updated test for when long int is not 8 byte

    Updated test for when long int is not 8 byte

    If sizeof(long int) != 8, the current tests will fail. Update the test to use limits.h to help know what LONG_MAX/MIN are. This also implies that iniparser_getlongint() will vary in terms of being able to accept different width integers, depending on architecture. The goal here was to fix the test, not change the API.

  • test_iniparser.c: missing comma in Test_iniparser_getboolean() token_true array declaration

    test_iniparser.c: missing comma in Test_iniparser_getboolean() token_true array declaration

    https://github.com/ndevilla/iniparser/blob/f858275f7f307eecba84c2f5429483f9f28007f8/test/test_iniparser.c#L458

    There's a missing comma in between the "YES" and "Y" entries in the token_true array declaration, which will result in the two strings being concatenated and thus the "Y" testcase being skipped.

    (This issue was found by coverity.)

Cross-platform C++ library providing a simple API to read and write INI-style configuration files

simpleini A cross-platform library that provides a simple API to read and write INI-style configuration files. It supports data files in ASCII, MBCS a

Aug 9, 2022
C++20 single-header library for embedding INI configs

ini-config A single-header library that converts INI-formatted string literals to a key-value pair list at compile-time. Requires C++20; tested on gcc

Jun 21, 2022
Small configuration file parser library for C.

libConfuse Introduction Documentation Examples Build & Install Origin & References Introduction libConfuse is a configuration file parser library writ

Aug 16, 2022
Header-only TOML config file parser and serializer for C++17 (and later!).
Header-only TOML config file parser and serializer for C++17 (and later!).

toml++ homepage ✨ This README is fine, but the toml++ homepage is better. ✨ Library features Header-only Supports the latest TOML release (v1.0.0), pl

Aug 8, 2022
config-loader is a static reflection framework written in C++17 from parse configuration file to native data structure.

config-loader is a static reflection framework written in C++17 from parse configuration file to native data structure.

Jul 20, 2022
ini file parser

Iniparser 4 I - Overview This modules offers parsing of ini files from the C level. See a complete documentation in HTML format, from this directory o

Aug 8, 2022
Simple .INI file parser in C, good for embedded systems

inih (INI Not Invented Here) inih (INI Not Invented Here) is a simple .INI file parser written in C. It's only a couple of pages of code, and it was d

Aug 17, 2022
ini file parser

Iniparser 4 I - Overview This modules offers parsing of ini files from the C level. See a complete documentation in HTML format, from this directory o

Aug 8, 2022
BLLIP reranking parser (also known as Charniak-Johnson parser, Charniak parser, Brown reranking parser) See http://pypi.python.org/pypi/bllipparser/ for Python module.

BLLIP Reranking Parser Copyright Mark Johnson, Eugene Charniak, 24th November 2005 --- August 2006 We request acknowledgement in any publications that

Aug 15, 2022
BLLIP reranking parser (also known as Charniak-Johnson parser, Charniak parser, Brown reranking parser)
BLLIP reranking parser (also known as Charniak-Johnson parser, Charniak parser, Brown reranking parser)

BLLIP reranking parser (also known as Charniak-Johnson parser, Charniak parser, Brown reranking parser)

Aug 15, 2022
A small and portable INI file library with read/write support

minIni minIni is a portable and configurable library for reading and writing ".INI" files. At just below 900 lines of commented source code, minIni tr

Aug 8, 2022
Cross-platform C++ library providing a simple API to read and write INI-style configuration files

simpleini A cross-platform library that provides a simple API to read and write INI-style configuration files. It supports data files in ASCII, MBCS a

Aug 9, 2022
C++20 single-header library for embedding INI configs

ini-config A single-header library that converts INI-formatted string literals to a key-value pair list at compile-time. Requires C++20; tested on gcc

Jun 21, 2022
Blog post on using a custom Bash builtin to parse INI config files

Writing a Bash Builtin in C to Parse INI Configs Why Not Just Parse INI Configs With Bash? Shell languages such as Bash excel at certain tasks, such a

Apr 6, 2022
tiny HTTP parser written in C (used in HTTP::Parser::XS et al.)
tiny HTTP parser written in C (used in HTTP::Parser::XS et al.)

PicoHTTPParser Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase, Shigeo Mitsunari PicoHTTPParser is a tiny, primitive, fast HTTP r

Aug 13, 2022
Fast C/C++ CSS Parser (Cascading Style Sheets Parser)

MyCSS — a pure C CSS parser MyCSS is a fast CSS Parser implemented as a pure C99 library with the ability to build without dependencies. Mailing List:

Jun 18, 2022
udmp-parser: A Windows user minidump C++ parser library.
udmp-parser: A Windows user minidump C++ parser library.

udmp-parser: A Windows user minidump C++ parser library. This is a cross-platform (Windows / Linux / OSX / x86 / x64) C++ library that parses Windows

Jul 1, 2022
Small configuration file parser library for C.

libConfuse Introduction Documentation Examples Build & Install Origin & References Introduction libConfuse is a configuration file parser library writ

Aug 16, 2022
Header-only TOML config file parser and serializer for C++17 (and later!).
Header-only TOML config file parser and serializer for C++17 (and later!).

toml++ homepage ✨ This README is fine, but the toml++ homepage is better. ✨ Library features Header-only Supports the latest TOML release (v1.0.0), pl

Aug 8, 2022
a header-file-only, JSON parser serializer in C++

PicoJSON - a C++ JSON parser / serializer Copyright © 2009-2010 Cybozu Labs, Inc. Copyright © 2011-2015 Kazuho Oku Licensed under 2-clause BSD license

Aug 5, 2022