]> git.sesse.net Git - plocate/blobdiff - plocate.cpp
Reset string explicitely to prevent undefined behavior
[plocate] / plocate.cpp
index 7182ee892dfa839b5b50794a4e22582500759996..36f087e348df241398dbfec4a317e198d1e19184 100644 (file)
@@ -55,6 +55,7 @@ bool patterns_are_regex = false;
 bool use_extended_regex = false;
 bool match_basename = false;
 bool check_existence = false;
+bool ignore_visibility = false;
 int64_t limit_matches = numeric_limits<int64_t>::max();
 int64_t limit_left = numeric_limits<int64_t>::max();
 bool stdout_is_tty = false;
@@ -114,6 +115,9 @@ Corpus::Corpus(int fd, const char *filename_for_errors, IOUringEngine *engine)
                // This too. (We ignore the other max_version 2 fields.)
                hdr.check_visibility = true;
        }
+       if (ignore_visibility) {
+               hdr.check_visibility = false;
+       }
 }
 
 Corpus::~Corpus()
@@ -485,6 +489,7 @@ uint64_t do_search_file(const vector<Needle> &needles, const std::string &filena
        start = steady_clock::now();
        if (access("/", R_OK | X_OK)) {
                // We can't find anything, no need to bother...
+               close(fd);
                return 0;
        }
 
@@ -530,6 +535,7 @@ uint64_t do_search_file(const vector<Needle> &needles, const std::string &filena
                uint64_t matched = scan_all_docids(needles, fd, corpus);
                dprintf("Done in %.1f ms, found %" PRId64 " matches.\n",
                        1e3 * duration<float>(steady_clock::now() - start).count(), matched);
+               close(fd);
                return matched;
        }
 
@@ -588,6 +594,7 @@ uint64_t do_search_file(const vector<Needle> &needles, const std::string &filena
        dprintf("Hashtable lookups done after %.1f ms.\n", 1e3 * duration<float>(steady_clock::now() - start).count());
 
        if (should_early_exit) {
+               close(fd);
                return 0;
        }
 
@@ -673,6 +680,7 @@ uint64_t do_search_file(const vector<Needle> &needles, const std::string &filena
        }
        engine.finish();
        if (done) {
+               close(fd);
                return 0;
        }
        dprintf("Intersection done after %.1f ms. Doing final verification and printing:\n",
@@ -681,6 +689,7 @@ uint64_t do_search_file(const vector<Needle> &needles, const std::string &filena
        uint64_t matched = scan_docids(needles, cur_candidates, corpus, &engine);
        dprintf("Done in %.1f ms, found %" PRId64 " matches.\n",
                1e3 * duration<float>(steady_clock::now() - start).count(), matched);
+       close(fd);
        return matched;
 }
 
@@ -790,6 +799,7 @@ void parse_dbpaths(const char *ptr, vector<string> *output)
                if (*ptr == ':') {
                        // Separator.
                        output->push_back(move(str));
+                       str.clear();
                        ++ptr;
                        continue;
                }
@@ -834,6 +844,7 @@ int main(int argc, char **argv)
 
        constexpr int EXTENDED_REGEX = 1000;
        constexpr int FLUSH_CACHE = 1001;
+       constexpr int IGNORE_VISIBILITY = 1002;
        static const struct option long_options[] = {
                { "help", no_argument, 0, 'h' },
                { "count", no_argument, 0, 'c' },
@@ -852,6 +863,9 @@ int main(int argc, char **argv)
                { "debug", no_argument, 0, 'D' },  // Not documented.
                // Enable to test cold-cache behavior (except for access()). Not documented.
                { "flush-cache", no_argument, 0, FLUSH_CACHE },
+               // Mostly useful to dump out the entire database, even if the given directories
+               // are gone. Disables sgid due to security. Not documented.
+               { "ignore-visibility", no_argument, 0, IGNORE_VISIBILITY },
                { 0, 0, 0, 0 }
        };
 
@@ -917,17 +931,22 @@ int main(int argc, char **argv)
                case 'V':
                        version();
                        break;
+               case IGNORE_VISIBILITY:
+                       ignore_visibility = true;
+                       break;
                default:
                        exit(1);
                }
        }
 
-       if (use_debug || flush_cache) {
+       if (use_debug || flush_cache || ignore_visibility) {
                // Debug information would leak information about which files exist,
                // so drop setgid before we open the file; one would either need to run
                // as root, or use a locally-built file. Doing the same thing for
                // flush_cache is mostly paranoia, in an attempt to prevent random users
                // from making plocate slow for everyone else.
+               // --ignore-visibility is obvious; if we allowed to keep sgid with
+               // that flag on, it would subvert the entire security model.
                if (setgid(getgid()) != 0) {
                        perror("setgid");
                        exit(EXIT_FAILURE);