Issue 8066 - mdb_load truncates long values when resizing buffer
Summary: mdb_load truncates long values when resizing buffer
Status: VERIFIED FIXED
Alias: None
Product: OpenLDAP
Classification: Unclassified
Component: slapd (show other issues)
Version: unspecified
Hardware: All All
: --- normal
Target Milestone: ---
Assignee: OpenLDAP project
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-02-25 23:29 UTC by catwell@archlinux.us
Modified: 2015-07-02 17:48 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description catwell@archlinux.us 2015-02-25 23:29:22 UTC
Full_Name: Pierre Chapuis
Version: master
OS: GNU/Linux
URL: ftp://ftp.openldap.org/incoming/
Submission from: (NULL) (82.238.40.212)


Description:

    Starting from 2048, the first input line larger than any power of two N
    is truncated to N-1. This results in truncated values in the database.

Explanation:

    In the code that resizes the input buffer, fgets() is used.
    fgets(*, n, *) reads a maximum of n-1 characters and 0-terminates
    the string. When the next chunk is read, the '\0' remains in the
    string. Later, strlen() is used and the string is truncated.

Proposed fix:

    A patch against the current OpenLDAP master llllows.

---

 libraries/liblmdb/mdb_load.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libraries/liblmdb/mdb_load.c b/libraries/liblmdb/mdb_load.c
index f626692..e86b6fd 100644
--- a/libraries/liblmdb/mdb_load.c
+++ b/libraries/liblmdb/mdb_load.c
@@ -218,7 +218,7 @@ badend:
                }
                c1 = buf->mv_data;
                c1 += buf->mv_size;
-               if (fgets((char *)c1, buf->mv_size, stdin) == NULL) {D%D
+               if (fgets((char *)c1-1, buf->mv_size+1, stdin) == NULL) {
                        Eof = 1;
                        badend();
                        return EOF;

---
Comment 1 catwell@archlinux.us 2015-02-26 08:00:04 UTC
For what it's worth, here is a slightly better patch.
The previous one would start the strlen() one character
too far. I don't think it would have much consequence
in practice, but this should be safer.

---
 libraries/liblmdb/mdb_load.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/libraries/liblmdb/mdb_load.c b/libraries/liblmdb/mdb_load.c
index f626692..960d23d 100644
--- a/libraries/liblmdb/mdb_load.c
+++ b/libraries/liblmdb/mdb_load.c
@@ -216,9 +216,8 @@ badend:
                                prog, lineno);
                        return EOF;
                }
-               c1 = buf->mv_data;
-               c1 += buf->mv_size;
-               if (fgets((char *)c1, buf->mv_size, stdin) == NULL) {
+               c1 = buf->mv_data + buf->mv_size - 1;
+               if (fgets((char *)c1, buf->mv_size+1, stdin) == NULL) {
                        Eof = 1;
                        badend();
                        return EOF;
-- 
Pierre Chapuis


Comment 2 Howard Chu 2015-02-26 21:37:44 UTC
catwell@archlinux.us wrote:
> Full_Name: Pierre Chapuis
> Version: master
> OS: GNU/Linux
> URL: ftp://ftp.openldap.org/incoming/
> Submission from: (NULL) (82.238.40.212)
>
>
> Description:
>
>      Starting from 2048, the first input line larger than any power of two N
>      is truncated to N-1. This results in truncated values in the database.

Thanks for the report. Fixed now in mdb.master
>
> Explanation:
>
>      In the code that resizes the input buffer, fgets() is used.
>      fgets(*, n, *) reads a maximum of n-1 characters and 0-terminates
>      the string. When the next chunk is read, the '\0' remains in the
>      string. Later, strlen() is used and the string is truncated.
>
> Proposed fix:
>
>      A patch against the current OpenLDAP master llllows.
>
> ---
>
>   libraries/liblmdb/mdb_load.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/libraries/liblmdb/mdb_load.c b/libraries/liblmdb/mdb_load.c
> index f626692..e86b6fd 100644
> --- a/libraries/liblmdb/mdb_load.c
> +++ b/libraries/liblmdb/mdb_load.c
> @@ -218,7 +218,7 @@ badend:
>                  }
>                  c1 = buf->mv_data;
>                  c1 += buf->mv_size;
> -               if (fgets((char *)c1, buf->mv_size, stdin) == NULL) {D%D
> +               if (fgets((char *)c1-1, buf->mv_size+1, stdin) == NULL) {
>                          Eof = 1;
>                          badend();
>                          return EOF;
>
> ---
>
>
>


-- 
   -- Howard Chu
   CTO, Symas Corp.           http://www.symas.com
   Director, Highland Sun     http://highlandsun.com/hyc/
   Chief Architect, OpenLDAP  http://www.openldap.org/project/

Comment 3 Howard Chu 2015-02-26 21:39:00 UTC
changed notes
changed state Open to Test
moved from Incoming to Software Bugs
Comment 4 Quanah Gibson-Mount 2015-02-27 23:15:55 UTC
changed notes
changed state Test to Release
Comment 5 OpenLDAP project 2015-07-02 17:48:24 UTC
fixed in mdb.master
fixed in mdb 0.9 (0.9.15 release)
fixed in master
fixed in RE25
fixed in RE24 (2.4.41 release)
Comment 6 Quanah Gibson-Mount 2015-07-02 17:48:24 UTC
changed notes
changed state Release to Closed