diff options
| -rw-r--r-- | dbus/dbus-sysdeps-unix.c | 65 | ||||
| -rw-r--r-- | dbus/dbus-sysdeps-util-unix.c | 58 | 
2 files changed, 96 insertions, 27 deletions
| diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index 64d925d9..c96499a6 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -1487,28 +1487,60 @@ fill_user_info (DBusUserInfo       *info,    {      struct passwd *p;      int result; -    char buf[1024]; +    size_t buflen; +    char *buf;      struct passwd p_str; -    p = NULL; +    /* retrieve maximum needed size for buf */ +    buflen = sysconf (_SC_GETPW_R_SIZE_MAX); + +    if (buflen <= 0) +      buflen = 1024; + +    result = -1; +    while (1) +      { +        buf = dbus_malloc (buflen); +        if (buf == NULL) +          { +            dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); +            return FALSE; +          } + +        p = NULL;  #ifdef HAVE_POSIX_GETPWNAM_R -    if (uid != DBUS_UID_UNSET) -      result = getpwuid_r (uid, &p_str, buf, sizeof (buf), -                           &p); -    else -      result = getpwnam_r (username_c, &p_str, buf, sizeof (buf), -                           &p); +        if (uid != DBUS_UID_UNSET) +          result = getpwuid_r (uid, &p_str, buf, buflen, +                               &p); +        else +          result = getpwnam_r (username_c, &p_str, buf, buflen, +                               &p);  #else -    if (uid != DBUS_UID_UNSET) -      p = getpwuid_r (uid, &p_str, buf, sizeof (buf)); -    else -      p = getpwnam_r (username_c, &p_str, buf, sizeof (buf)); -    result = 0; +        if (uid != DBUS_UID_UNSET) +          p = getpwuid_r (uid, &p_str, buf, buflen); +        else +          p = getpwnam_r (username_c, &p_str, buf, buflen); +        result = 0;  #endif /* !HAVE_POSIX_GETPWNAM_R */ +        //Try a bigger buffer if ERANGE was returned +        if (result == ERANGE && buflen < 512 * 1024) +          { +            dbus_free (buf); +            buflen *= 2; +          } +        else +          { +            break; +          } +      }      if (result == 0 && p == &p_str)        {          if (!fill_user_info_from_passwd (p, info, error)) -          return FALSE; +          { +            dbus_free (buf); +            return FALSE; +          } +        dbus_free (buf);        }      else        { @@ -1516,6 +1548,7 @@ fill_user_info (DBusUserInfo       *info,                          "User \"%s\" unknown or no memory to allocate password entry\n",                          username_c ? username_c : "???");          _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???"); +        dbus_free (buf);          return FALSE;        }    } @@ -1532,7 +1565,9 @@ fill_user_info (DBusUserInfo       *info,      if (p != NULL)        {          if (!fill_user_info_from_passwd (p, info, error)) -          return FALSE; +          { +            return FALSE; +          }        }      else        { diff --git a/dbus/dbus-sysdeps-util-unix.c b/dbus/dbus-sysdeps-util-unix.c index 9ff3fbc1..55eb9346 100644 --- a/dbus/dbus-sysdeps-util-unix.c +++ b/dbus/dbus-sysdeps-util-unix.c @@ -828,31 +828,65 @@ fill_group_info (DBusGroupInfo    *info,    {      struct group *g;      int result; -    char buf[1024]; +    size_t buflen; +    char *buf;      struct group g_str; +    dbus_bool_t b; -    g = NULL; -#ifdef HAVE_POSIX_GETPWNAM_R +    /* retrieve maximum needed size for buf */ +    buflen = sysconf (_SC_GETGR_R_SIZE_MAX); -    if (group_c_str) -      result = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf), -                           &g); -    else -      result = getgrgid_r (gid, &g_str, buf, sizeof (buf), -                           &g); +    if (buflen <= 0) +      buflen = 1024; + +    result = -1; +    while (1) +      { +        buf = dbus_malloc (buflen); +        if (buf == NULL) +          { +            dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); +            return FALSE; +          } + +        g = NULL; +#ifdef HAVE_POSIX_GETPWNAM_R +        if (group_c_str) +          result = getgrnam_r (group_c_str, &g_str, buf, buflen, +                               &g); +        else +          result = getgrgid_r (gid, &g_str, buf, buflen, +                               &g);  #else -    g = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf)); -    result = 0; +        g = getgrnam_r (group_c_str, &g_str, buf, buflen); +        result = 0;  #endif /* !HAVE_POSIX_GETPWNAM_R */ +        /* Try a bigger buffer if ERANGE was returned: +           https://bugs.freedesktop.org/show_bug.cgi?id=16727 +        */ +        if (result == ERANGE && buflen < 512 * 1024) +          { +            dbus_free (buf); +            buflen *= 2; +          } +        else +          { +            break; +          } +      } +      if (result == 0 && g == &g_str)        { -        return fill_user_info_from_group (g, info, error); +        b = fill_user_info_from_group (g, info, error); +        dbus_free (buf); +        return b;        }      else        {          dbus_set_error (error, _dbus_error_from_errno (errno),                          "Group %s unknown or failed to look it up\n",                          group_c_str ? group_c_str : "???"); +        dbus_free (buf);          return FALSE;        }    } | 
