diff options
Diffstat (limited to 'apt-pkg/contrib')
-rw-r--r-- | apt-pkg/contrib/cmndline.cc | 14 | ||||
-rw-r--r-- | apt-pkg/contrib/configuration.cc | 168 | ||||
-rw-r--r-- | apt-pkg/contrib/error.h | 2 | ||||
-rw-r--r-- | apt-pkg/contrib/fileutl.cc | 2 | ||||
-rw-r--r-- | apt-pkg/contrib/gpgv.cc | 50 | ||||
-rw-r--r-- | apt-pkg/contrib/mmap.cc | 6 | ||||
-rw-r--r-- | apt-pkg/contrib/mmap.h | 2 | ||||
-rw-r--r-- | apt-pkg/contrib/proxy.cc | 2 | ||||
-rw-r--r-- | apt-pkg/contrib/strutl.cc | 18 | ||||
-rw-r--r-- | apt-pkg/contrib/strutl.h | 2 |
10 files changed, 246 insertions, 20 deletions
diff --git a/apt-pkg/contrib/cmndline.cc b/apt-pkg/contrib/cmndline.cc index c8a6e2787..029ec3060 100644 --- a/apt-pkg/contrib/cmndline.cc +++ b/apt-pkg/contrib/cmndline.cc @@ -402,21 +402,27 @@ void CommandLine::SaveInConfig(unsigned int const &argc, char const * const * co bool closeQuote = false; for (unsigned int i = 0; i < argc && length < sizeof(cmdline); ++i, ++length) { - for (unsigned int j = 0; argv[i][j] != '\0' && length < sizeof(cmdline)-1; ++j, ++length) + for (unsigned int j = 0; argv[i][j] != '\0' && length < sizeof(cmdline)-2; ++j) { - cmdline[length] = argv[i][j]; + // we can't really sensibly deal with quoting so skip it + if (strchr("\"\'\r\n", argv[i][j]) != nullptr) + continue; + cmdline[length++] = argv[i][j]; if (lastWasOption == true && argv[i][j] == '=') { // That is possibly an option: Quote it if it includes spaces, // the benefit is that this will eliminate also most false positives const char* c = strchr(&argv[i][j+1], ' '); if (c == NULL) continue; - cmdline[++length] = '"'; + cmdline[length++] = '\''; closeQuote = true; } } if (closeQuote == true) - cmdline[length++] = '"'; + { + cmdline[length++] = '\''; + closeQuote = false; + } // Problem: detects also --hello if (cmdline[length-1] == 'o') lastWasOption = true; diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc index 9007bf9ec..78a98d614 100644 --- a/apt-pkg/contrib/configuration.cc +++ b/apt-pkg/contrib/configuration.cc @@ -31,10 +31,13 @@ #include <string.h> #include <algorithm> +#include <iterator> #include <string> #include <stack> #include <vector> #include <fstream> +#include <sstream> +#include <unordered_map> #include <apti18n.h> @@ -43,6 +46,155 @@ using namespace std; Configuration *_config = new Configuration; +/* TODO: This config verification shouldn't be using a static variable + but a Cnf-member – but that would need ABI breaks and stuff and for now + that really is an apt-dev-only tool, so it isn't that bad that it is + unusable and allaround a bit strange */ +enum class APT_HIDDEN ConfigType { UNDEFINED, INT, BOOL, STRING, STRING_OR_BOOL, STRING_OR_LIST, FILE, DIR, LIST, PROGRAM_PATH = FILE }; +APT_HIDDEN std::unordered_map<std::string, ConfigType> apt_known_config {}; +static std::string getConfigTypeString(ConfigType const type) /*{{{*/ +{ + switch (type) + { + case ConfigType::UNDEFINED: return "UNDEFINED"; + case ConfigType::INT: return "INT"; + case ConfigType::BOOL: return "BOOL"; + case ConfigType::STRING: return "STRING"; + case ConfigType::STRING_OR_BOOL: return "STRING_OR_BOOL"; + case ConfigType::FILE: return "FILE"; + case ConfigType::DIR: return "DIR"; + case ConfigType::LIST: return "LIST"; + case ConfigType::STRING_OR_LIST: return "STRING_OR_LIST"; + } + return "UNKNOWN"; +} + /*}}}*/ +static ConfigType getConfigType(std::string const &type) /*{{{*/ +{ + if (type == "<INT>") + return ConfigType::INT; + else if (type == "<BOOL>") + return ConfigType::BOOL; + else if (type == "<STRING>") + return ConfigType::STRING; + else if (type == "<STRING_OR_BOOL>") + return ConfigType::STRING_OR_BOOL; + else if (type == "<FILE>") + return ConfigType::FILE; + else if (type == "<DIR>") + return ConfigType::DIR; + else if (type == "<LIST>") + return ConfigType::LIST; + else if (type == "<STRING_OR_LIST>") + return ConfigType::STRING_OR_LIST; + else if (type == "<PROGRAM_PATH>") + return ConfigType::PROGRAM_PATH; + return ConfigType::UNDEFINED; +} + /*}}}*/ +// checkFindConfigOptionType - workhorse of option checking /*{{{*/ +static void checkFindConfigOptionTypeInternal(std::string name, ConfigType const type) +{ + std::transform(name.begin(), name.end(), name.begin(), ::tolower); + auto known = apt_known_config.find(name); + if (known == apt_known_config.cend()) + { + auto const rcolon = name.rfind(':'); + if (rcolon != std::string::npos) + { + known = apt_known_config.find(name.substr(0, rcolon) + ":*"); + if (known == apt_known_config.cend()) + { + auto const parts = StringSplit(name, "::"); + size_t psize = parts.size(); + if (psize > 1) + { + for (size_t max = psize; max != 1; --max) + { + std::ostringstream os; + std::copy(parts.begin(), parts.begin() + max, std::ostream_iterator<std::string>(os, "::")); + os << "**"; + known = apt_known_config.find(os.str()); + if (known != apt_known_config.cend() && known->second == ConfigType::UNDEFINED) + return; + } + for (size_t max = psize - 1; max != 1; --max) + { + std::ostringstream os; + std::copy(parts.begin(), parts.begin() + max - 1, std::ostream_iterator<std::string>(os, "::")); + os << "*::"; + std::copy(parts.begin() + max + 1, parts.end() - 1, std::ostream_iterator<std::string>(os, "::")); + os << *(parts.end() - 1); + known = apt_known_config.find(os.str()); + if (known != apt_known_config.cend()) + break; + } + } + } + } + } + if (known == apt_known_config.cend()) + _error->Warning("Using unknown config option »%s« of type %s", + name.c_str(), getConfigTypeString(type).c_str()); + else if (known->second != type) + { + if (known->second == ConfigType::DIR && type == ConfigType::FILE) + ; // implementation detail + else if (type == ConfigType::STRING && (known->second == ConfigType::FILE || known->second == ConfigType::DIR)) + ; // TODO: that might be an error or not, we will figure this out later + else if (known->second == ConfigType::STRING_OR_BOOL && (type == ConfigType::BOOL || type == ConfigType::STRING)) + ; + else if (known->second == ConfigType::STRING_OR_LIST && (type == ConfigType::LIST || type == ConfigType::STRING)) + ; + else + _error->Warning("Using config option »%s« of type %s as a type %s", + name.c_str(), getConfigTypeString(known->second).c_str(), getConfigTypeString(type).c_str()); + } +} +static void checkFindConfigOptionType(char const * const name, ConfigType const type) +{ + if (apt_known_config.empty()) + return; + checkFindConfigOptionTypeInternal(name, type); +} + /*}}}*/ +static bool LoadConfigurationIndex(std::string const &filename) /*{{{*/ +{ + apt_known_config.clear(); + if (filename.empty()) + return true; + Configuration Idx; + if (ReadConfigFile(Idx, filename) == false) + return false; + + Configuration::Item const * Top = Idx.Tree(nullptr); + if (unlikely(Top == nullptr)) + return false; + + do { + if (Top->Value.empty() == false) + { + std::string fulltag = Top->FullTag(); + std::transform(fulltag.begin(), fulltag.end(), fulltag.begin(), ::tolower); + apt_known_config.emplace(std::move(fulltag), getConfigType(Top->Value)); + } + + if (Top->Child != nullptr) + { + Top = Top->Child; + continue; + } + + while (Top != nullptr && Top->Next == nullptr) + Top = Top->Parent; + if (Top != nullptr) + Top = Top->Next; + } while (Top != nullptr); + + return true; +} + /*}}}*/ + // Configuration::Configuration - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -160,6 +312,7 @@ Configuration::Item *Configuration::Lookup(const char *Name,bool const &Create) /* */ string Configuration::Find(const char *Name,const char *Default) const { + checkFindConfigOptionType(Name, ConfigType::STRING); const Item *Itm = Lookup(Name); if (Itm == 0 || Itm->Value.empty() == true) { @@ -179,6 +332,7 @@ string Configuration::Find(const char *Name,const char *Default) const */ string Configuration::FindFile(const char *Name,const char *Default) const { + checkFindConfigOptionType(Name, ConfigType::FILE); const Item *RootItem = Lookup("RootDir"); std::string result = (RootItem == 0) ? "" : RootItem->Value; if(result.empty() == false && result[result.size() - 1] != '/') @@ -233,6 +387,7 @@ string Configuration::FindFile(const char *Name,const char *Default) const /* This is like findfile execept the result is terminated in a / */ string Configuration::FindDir(const char *Name,const char *Default) const { + checkFindConfigOptionType(Name, ConfigType::DIR); string Res = FindFile(Name,Default); if (Res.end()[-1] != '/') { @@ -249,6 +404,7 @@ string Configuration::FindDir(const char *Name,const char *Default) const /* Returns a vector of config values under the given item */ vector<string> Configuration::FindVector(const char *Name, std::string const &Default, bool const Keys) const { + checkFindConfigOptionType(Name, ConfigType::LIST); vector<string> Vec; const Item *Top = Lookup(Name); if (Top == NULL) @@ -274,6 +430,7 @@ vector<string> Configuration::FindVector(const char *Name, std::string const &De /* */ int Configuration::FindI(const char *Name,int const &Default) const { + checkFindConfigOptionType(Name, ConfigType::INT); const Item *Itm = Lookup(Name); if (Itm == 0 || Itm->Value.empty() == true) return Default; @@ -291,6 +448,7 @@ int Configuration::FindI(const char *Name,int const &Default) const /* */ bool Configuration::FindB(const char *Name,bool const &Default) const { + checkFindConfigOptionType(Name, ConfigType::BOOL); const Item *Itm = Lookup(Name); if (Itm == 0 || Itm->Value.empty() == true) return Default; @@ -774,7 +932,8 @@ bool ReadConfigFile(Configuration &Conf,const string &FName,bool const &AsSectio if ((*I == '/' && I + 1 != End && I[1] == '/') || (*I == '#' && strcmp(string(I,I+6).c_str(),"#clear") != 0 && - strcmp(string(I,I+8).c_str(),"#include") != 0)) + strcmp(string(I,I+8).c_str(),"#include") != 0 && + strcmp(string(I,I+strlen("#x-apt-configure-index")).c_str(), "#x-apt-configure-index") != 0)) { End = I; break; @@ -889,7 +1048,7 @@ bool ReadConfigFile(Configuration &Conf,const string &FName,bool const &AsSectio { Stack.push(ParentTag); - /* Make sectional tags incorperate the section into the + /* Make sectional tags incorporate the section into the tag string */ if (AsSectional == true && Word.empty() == false) { @@ -939,6 +1098,11 @@ bool ReadConfigFile(Configuration &Conf,const string &FName,bool const &AsSectio return _error->Error(_("Syntax error %s:%u: Included from here"),FName.c_str(),CurLine); } } + else if (Tag == "x-apt-configure-index") + { + if (LoadConfigurationIndex(Word) == false) + return _error->Warning("Loading the configure index %s in file %s:%u failed!", Word.c_str(), FName.c_str(), CurLine); + } else return _error->Error(_("Syntax error %s:%u: Unsupported directive '%s'"),FName.c_str(),CurLine,Tag.c_str()); } diff --git a/apt-pkg/contrib/error.h b/apt-pkg/contrib/error.h index bcaa7c995..5ad408d25 100644 --- a/apt-pkg/contrib/error.h +++ b/apt-pkg/contrib/error.h @@ -3,7 +3,7 @@ // $Id: error.h,v 1.8 2001/05/07 05:06:52 jgg Exp $ /* ###################################################################### - Global Erorr Class - Global error mechanism + Global Error Class - Global error mechanism This class has a single global instance. When a function needs to generate an error condition, such as a read error, it calls a member diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index f3c7b6d3b..a90cd647a 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -2949,7 +2949,7 @@ static std::string APT_NONNULL(1) GetTempDirEnv(char const * const env) /*{{{*/ stat(tmpdir, &st) != 0 || (st.st_mode & S_IFDIR) == 0) // exists and is directory tmpdir = "/tmp"; else if (geteuid() != 0 && // root can do everything anyway - faccessat(-1, tmpdir, R_OK | W_OK | X_OK, AT_EACCESS | AT_SYMLINK_NOFOLLOW) != 0) // current user has rwx access to directory + faccessat(AT_FDCWD, tmpdir, R_OK | W_OK | X_OK, AT_EACCESS) != 0) // current user has rwx access to directory tmpdir = "/tmp"; return string(tmpdir); diff --git a/apt-pkg/contrib/gpgv.cc b/apt-pkg/contrib/gpgv.cc index cdf1e7f42..d4ccf47c7 100644 --- a/apt-pkg/contrib/gpgv.cc +++ b/apt-pkg/contrib/gpgv.cc @@ -146,7 +146,6 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG, } enum { DETACHED, CLEARSIGNED } releaseSignature = (FileGPG != File) ? DETACHED : CLEARSIGNED; - std::vector<std::string> dataHeader; char * sig = NULL; char * data = NULL; char * conf = nullptr; @@ -205,7 +204,7 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG, message.OpenDescriptor(dataFd, FileFd::WriteOnly, true); if (signature.Failed() == true || message.Failed() == true || - SplitClearSignedFile(File, &message, &dataHeader, &signature) == false) + SplitClearSignedFile(File, &message, nullptr, &signature) == false) { apt_error(std::cerr, statusfd, fd, "Splitting up %s into data and signature failed", File.c_str()); local_exit(112); @@ -304,6 +303,20 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG, } /*}}}*/ // SplitClearSignedFile - split message into data/signature /*{{{*/ +static int GetLineErrno(char **lineptr, size_t *n, FILE *stream, std::string const &InFile) +{ + int result; + + errno = 0; + result = getline(lineptr, n, stream); + if (errno != 0) + { + _error->Errno("getline", "Could not read from %s", InFile.c_str()); + return -1; + } + + return result; +} bool SplitClearSignedFile(std::string const &InFile, FileFd * const ContentFile, std::vector<std::string> * const ContentHeader, FileFd * const SignatureFile) { @@ -316,10 +329,13 @@ bool SplitClearSignedFile(std::string const &InFile, FileFd * const ContentFile, bool skip_until_empty_line = false; bool found_signature = false; bool first_line = true; + bool signed_message_not_on_first_line = false; + bool found_garbage = false; char *buf = NULL; size_t buf_size = 0; - while (getline(&buf, &buf_size, in) != -1) + _error->PushToStack(); + while (GetLineErrno(&buf, &buf_size, in, InFile) != -1) { _strrstrip(buf); if (found_message_start == false) @@ -329,6 +345,8 @@ bool SplitClearSignedFile(std::string const &InFile, FileFd * const ContentFile, found_message_start = true; skip_until_empty_line = true; } + else + signed_message_not_on_first_line = found_garbage = true; } else if (skip_until_empty_line == true) { @@ -366,6 +384,8 @@ bool SplitClearSignedFile(std::string const &InFile, FileFd * const ContentFile, if (ContentFile != NULL) ContentFile->Write(dashfree, strlen(dashfree)); } + else + found_garbage = true; } else if (found_signature == true) { @@ -378,11 +398,33 @@ bool SplitClearSignedFile(std::string const &InFile, FileFd * const ContentFile, found_signature = false; // look for other signatures } // all the rest is whitespace, unsigned garbage or additional message blocks we ignore + else + found_garbage = true; } fclose(in); if (buf != NULL) free(buf); + // Flush the files. Errors will be checked below. + if (SignatureFile != nullptr) + SignatureFile->Flush(); + if (ContentFile != nullptr) + ContentFile->Flush(); + + if (found_message_start) + { + if (signed_message_not_on_first_line) + _error->Warning("Clearsigned file '%s' does not start with a signed message block.", InFile.c_str()); + else if (found_garbage) + _error->Warning("Clearsigned file '%s' contains unsigned lines.", InFile.c_str()); + } + + // An error occurred during reading - propagate it up + bool const hasErrored = _error->PendingError(); + _error->MergeWithStack(); + if (hasErrored) + return false; + if (found_signature == true) return _error->Error("Signature in file %s wasn't closed", InFile.c_str()); @@ -406,7 +448,7 @@ bool OpenMaybeClearSignedFile(std::string const &ClearSignedFileName, FileFd &Me free(message); return _error->Errno("mkstemp", "Couldn't create temporary file to work with %s", ClearSignedFileName.c_str()); } - // we have the fd, thats enough for us + // we have the fd, that's enough for us unlink(message); free(message); diff --git a/apt-pkg/contrib/mmap.cc b/apt-pkg/contrib/mmap.cc index f63f2eea1..fa93c91af 100644 --- a/apt-pkg/contrib/mmap.cc +++ b/apt-pkg/contrib/mmap.cc @@ -155,9 +155,9 @@ bool MMap::Close(bool DoSync) return true; } /*}}}*/ -// MMap::Sync - Syncronize the map with the disk /*{{{*/ +// MMap::Sync - Synchronize the map with the disk /*{{{*/ // --------------------------------------------------------------------- -/* This is done in syncronous mode - the docs indicate that this will +/* This is done in synchronous mode - the docs indicate that this will not return till all IO is complete */ bool MMap::Sync() { @@ -182,7 +182,7 @@ bool MMap::Sync() return true; } /*}}}*/ -// MMap::Sync - Syncronize a section of the file to disk /*{{{*/ +// MMap::Sync - Synchronize a section of the file to disk /*{{{*/ // --------------------------------------------------------------------- /* */ bool MMap::Sync(unsigned long Start,unsigned long Stop) diff --git a/apt-pkg/contrib/mmap.h b/apt-pkg/contrib/mmap.h index 1576cab91..b776959c2 100644 --- a/apt-pkg/contrib/mmap.h +++ b/apt-pkg/contrib/mmap.h @@ -10,7 +10,7 @@ from file fd's this function will use read and normal allocated memory. - Writing to a public mmap will always fully comit all changes when the + Writing to a public mmap will always fully commit all changes when the class is deleted. Ie it will rewrite the file, unless it is readonly The DynamicMMap class is used to help the on-disk data structure diff --git a/apt-pkg/contrib/proxy.cc b/apt-pkg/contrib/proxy.cc index 62cfba032..1b7a92c68 100644 --- a/apt-pkg/contrib/proxy.cc +++ b/apt-pkg/contrib/proxy.cc @@ -2,7 +2,7 @@ // Description /*{{{*/ /* ###################################################################### - Proxy - Proxy releated functions + Proxy - Proxy related functions ##################################################################### */ /*}}}*/ diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index cf8feb970..88113f7a4 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -27,6 +27,7 @@ #include <locale> #include <sstream> #include <string> +#include <sstream> #include <vector> #include <stddef.h> @@ -85,6 +86,17 @@ bool Startswith(const std::string &s, const std::string &start) return (s.compare(0, start.size(), start) == 0); } +std::string Join(std::vector<std::string> list, const std::string &sep) +{ + std::ostringstream oss; + for (auto it = list.begin(); it != list.end(); it++) + { + if (it != list.begin()) oss << sep; + oss << *it; + } + return oss.str(); +} + } } /*}}}*/ @@ -748,7 +760,7 @@ int StringToBool(const string &Text,int Default) // TimeRFC1123 - Convert a time_t into RFC1123 format /*{{{*/ // --------------------------------------------------------------------- /* This converts a time_t into a string time representation that is - year 2000 complient and timezone neutral */ + year 2000 compliant and timezone neutral */ string TimeRFC1123(time_t Date) { return TimeRFC1123(Date, false); @@ -1466,7 +1478,7 @@ string StripEpoch(const string &VerStr) // tolower_ascii - tolower() function that ignores the locale /*{{{*/ // --------------------------------------------------------------------- /* This little function is the most called method we have and tries - therefore to do the absolut minimum - and is notable faster than + therefore to do the absolute minimum - and is notable faster than standard tolower/toupper and as a bonus avoids problems with different locales - we only operate on ascii chars anyway. */ #undef tolower_ascii @@ -1480,7 +1492,7 @@ int tolower_ascii(int const c) // isspace_ascii - isspace() function that ignores the locale /*{{{*/ // --------------------------------------------------------------------- /* This little function is one of the most called methods we have and tries - therefore to do the absolut minimum - and is notable faster than + therefore to do the absolute minimum - and is notable faster than standard isspace() and as a bonus avoids problems with different locales - we only operate on ascii chars anyway. */ #undef isspace_ascii diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index b58e69cbd..ba41172fd 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -44,6 +44,8 @@ namespace APT { std::string Strip(const std::string &s); bool Endswith(const std::string &s, const std::string &ending); bool Startswith(const std::string &s, const std::string &starting); + std::string Join(std::vector<std::string> list, const std::string &sep); + } } |