From c114cbc9af4b5a07fb6e87b50f36e78aa8aba615 Mon Sep 17 00:00:00 2001 From: Kurtis Rader Date: Wed, 10 May 2017 22:07:01 -0700 Subject: [PATCH] lint: deal with `getpwent()` warnings This suppresses lint warnings about using `getpwent()` because there is only one context where fish uses it. Thus the fact it may not be thread safe is not relevant to fish. This also improves that call site in `completer_t::try_complete_user()` method by short-circuiting the loop when a match is found. --- src/complete.cpp | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/src/complete.cpp b/src/complete.cpp index 6abfe0d81..f0c546323 100644 --- a/src/complete.cpp +++ b/src/complete.cpp @@ -1172,7 +1172,7 @@ bool completer_t::try_complete_variable(const wcstring &str) { /// Try to complete the specified string as a username. This is used by ~USER type expansion. /// -/// \return 0 if unable to complete, 1 otherwise +/// \return false if unable to complete, true otherwise bool completer_t::try_complete_user(const wcstring &str) { #ifndef HAVE_GETPWENT // The getpwent() function does not exist on Android. A Linux user on Android isn't @@ -1184,48 +1184,43 @@ bool completer_t::try_complete_user(const wcstring &str) { const wchar_t *cmd = str.c_str(); const wchar_t *first_char = cmd; - if (*first_char != L'~' || wcschr(first_char, L'/')) { - return false; - } + if (*first_char != L'~' || wcschr(first_char, L'/')) return false; const wchar_t *user_name = first_char + 1; const wchar_t *name_end = wcschr(user_name, L'~'); - if (name_end) { - return false; - } + if (name_end) return false; double start_time = timef(); bool result = false; - struct passwd *pw; size_t name_len = wcslen(user_name); + // We don't bother with the thread-safe `getpwent_r()` variant because it isn't needed. This is + // only run in a completion context and thus will only be called from a single thread and there + // is no place else in fish where we call `getpwent()`. + struct passwd *pw; setpwent(); - while ((pw = getpwent()) != 0) { - double current_time = timef(); - if (current_time - start_time > 0.2) { - return 1; - } - - if (!pw->pw_name) { - continue; - } - + // cppcheck-suppress getpwentCalled + while ((pw = getpwent()) != NULL) { const wcstring pw_name_str = str2wcstring(pw->pw_name); const wchar_t *pw_name = pw_name_str.c_str(); if (wcsncmp(user_name, pw_name, name_len) == 0) { wcstring desc = format_string(COMPLETE_USER_DESC, pw_name); append_completion(&this->completions, &pw_name[name_len], desc, COMPLETE_NO_SPACE); - result = true; + break; } else if (wcsncasecmp(user_name, pw_name, name_len) == 0) { wcstring name = format_string(L"~%ls", pw_name); wcstring desc = format_string(COMPLETE_USER_DESC, pw_name); - append_completion(&this->completions, name, desc, COMPLETE_REPLACES_TOKEN | COMPLETE_DONT_ESCAPE | COMPLETE_NO_SPACE); result = true; + break; } + + // If we've spent too much time (more than 200 ms) doing this give up. + if (timef() - start_time > 0.2) break; } + endpwent(); return result; #endif