summaryrefslogtreecommitdiff
path: root/apt-pkg/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg/contrib')
-rw-r--r--apt-pkg/contrib/configuration.cc141
-rw-r--r--apt-pkg/contrib/fileutl.cc21
-rw-r--r--apt-pkg/contrib/gpgv.cc15
-rw-r--r--apt-pkg/contrib/mmap.cc2
-rw-r--r--apt-pkg/contrib/string_view.h26
-rw-r--r--apt-pkg/contrib/strutl.cc109
-rw-r--r--apt-pkg/contrib/strutl.h4
7 files changed, 143 insertions, 175 deletions
diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc
index 931df9f6c..a8fced724 100644
--- a/apt-pkg/contrib/configuration.cc
+++ b/apt-pkg/contrib/configuration.cc
@@ -21,6 +21,7 @@
#include <apt-pkg/fileutl.h>
#include <apt-pkg/macros.h>
#include <apt-pkg/strutl.h>
+#include <apt-pkg/string_view.h>
#include <ctype.h>
#include <regex.h>
@@ -861,107 +862,82 @@ bool ReadConfigFile(Configuration &Conf,const string &FName,bool const &AsSectio
// The input line with comments stripped.
std::string Fragment;
- // Expand tabs in the input line and remove leading and trailing
- // whitespace.
- {
- const int BufferSize = Input.size() * 8 + 1;
- char *Buffer = new char[BufferSize];
- try
- {
- memcpy(Buffer, Input.c_str(), Input.size() + 1);
-
- _strtabexpand(Buffer, BufferSize);
- _strstrip(Buffer);
- Input = Buffer;
- }
- catch(...)
- {
- delete[] Buffer;
- throw;
- }
- delete[] Buffer;
- }
+ // Expand tabs in the input line and remove leading and trailing whitespace.
+ Input = APT::String::Strip(SubstVar(Input, "\t", " "));
CurLine++;
// Now strip comments; if the whole line is contained in a
// comment, skip this line.
+ APT::StringView Line{Input.data(), Input.size()};
- // The first meaningful character in the current fragment; will
- // be adjusted below as we remove bytes from the front.
- std::string::const_iterator Start = Input.begin();
- // The last meaningful character in the current fragment.
- std::string::const_iterator End = Input.end();
-
- // Multi line comment
- if (InComment == true)
+ // continued Multi line comment
+ if (InComment)
{
- for (std::string::const_iterator I = Start;
- I != End; ++I)
+ size_t end = Line.find("*/");
+ if (end != APT::StringView::npos)
{
- if (*I == '*' && I + 1 != End && I[1] == '/')
- {
- Start = I + 2;
- InComment = false;
- break;
- }
+ Line.remove_prefix(end + 2);
+ InComment = false;
}
- if (InComment == true)
+ else
continue;
}
// Discard single line comments
- bool InQuote = false;
- for (std::string::const_iterator I = Start;
- I != End; ++I)
{
- if (*I == '"')
- InQuote = !InQuote;
- if (InQuote == true)
- continue;
-
- 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+strlen("#x-apt-configure-index")).c_str(), "#x-apt-configure-index") != 0))
+ size_t start = 0;
+ while ((start = Line.find("//", start)) != APT::StringView::npos)
{
- End = I;
+ if (std::count(Line.begin(), Line.begin() + start, '"') % 2 != 0)
+ {
+ ++start;
+ continue;
+ }
+ Line.remove_suffix(Line.length() - start);
+ break;
+ }
+ using APT::operator""_sv;
+ constexpr std::array<APT::StringView, 3> magicComments { "clear"_sv, "include"_sv, "x-apt-configure-index"_sv };
+ start = 0;
+ while ((start = Line.find('#', start)) != APT::StringView::npos)
+ {
+ if (std::count(Line.begin(), Line.begin() + start, '"') % 2 != 0 ||
+ std::any_of(magicComments.begin(), magicComments.end(), [&](auto const m) { return Line.compare(start+1, m.length(), m) == 0; }))
+ {
+ ++start;
+ continue;
+ }
+ Line.remove_suffix(Line.length() - start);
break;
}
}
// Look for multi line comments and build up the
// fragment.
- Fragment.reserve(End - Start);
- InQuote = false;
- for (std::string::const_iterator I = Start;
- I != End; ++I)
+ Fragment.reserve(Line.length());
{
- if (*I == '"')
- InQuote = !InQuote;
- if (InQuote == true)
- Fragment.push_back(*I);
- else if (*I == '/' && I + 1 != End && I[1] == '*')
- {
- InComment = true;
- for (std::string::const_iterator J = I;
- J != End; ++J)
+ size_t start = 0;
+ while ((start = Line.find("/*", start)) != APT::StringView::npos)
+ {
+ if (std::count(Line.begin(), Line.begin() + start, '"') % 2 != 0)
{
- if (*J == '*' && J + 1 != End && J[1] == '/')
- {
- // Pretend we just finished walking over the
- // comment, and don't add anything to the output
- // fragment.
- I = J + 1;
- InComment = false;
- break;
- }
+ start += 2;
+ continue;
}
-
- if (InComment == true)
- break;
+ Fragment.append(Line.data(), start);
+ auto const end = Line.find("*/", start + 2);
+ if (end == APT::StringView::npos)
+ {
+ Line.clear();
+ InComment = true;
+ break;
+ }
+ else
+ Line.remove_prefix(end + 2);
+ start = 0;
}
- else
- Fragment.push_back(*I);
+ if (not Line.empty())
+ Fragment.append(Line.data(), Line.length());
}
// Skip blank lines.
@@ -969,9 +945,9 @@ bool ReadConfigFile(Configuration &Conf,const string &FName,bool const &AsSectio
continue;
// The line has actual content; interpret what it means.
- InQuote = false;
- Start = Fragment.begin();
- End = Fragment.end();
+ bool InQuote = false;
+ auto Start = Fragment.cbegin();
+ auto End = Fragment.cend();
for (std::string::const_iterator I = Start;
I != End; ++I)
{
@@ -1150,10 +1126,13 @@ bool ReadConfigFile(Configuration &Conf,const string &FName,bool const &AsSectio
bool ReadConfigDir(Configuration &Conf,const string &Dir,
bool const &AsSectional, unsigned const &Depth)
{
+ _error->PushToStack();
auto const files = GetListOfFilesInDir(Dir, "conf", true, true);
+ auto const successfulList = not _error->PendingError();
+ _error->MergeWithStack();
return std::accumulate(files.cbegin(), files.cend(), true, [&](bool good, auto const &file) {
return ReadConfigFile(Conf, file, AsSectional, Depth) && good;
- });
+ }) && successfulList;
}
/*}}}*/
// MatchAgainstConfig Constructor /*{{{*/
diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc
index e91c1acc3..091def3d4 100644
--- a/apt-pkg/contrib/fileutl.cc
+++ b/apt-pkg/contrib/fileutl.cc
@@ -1774,9 +1774,8 @@ public:
#endif
};
/*}}}*/
-
-class APT_HIDDEN ZstdFileFdPrivate : public FileFdPrivate
-{ /*{{{*/
+class APT_HIDDEN ZstdFileFdPrivate : public FileFdPrivate /*{{{*/
+{
#ifdef HAVE_ZSTD
ZSTD_DStream *dctx;
ZSTD_CStream *cctx;
@@ -1986,7 +1985,7 @@ class APT_HIDDEN ZstdFileFdPrivate : public FileFdPrivate
#endif
};
/*}}}*/
-class APT_HIDDEN LzmaFileFdPrivate: public FileFdPrivate { /*{{{*/
+class APT_HIDDEN LzmaFileFdPrivate: public FileFdPrivate { /*{{{*/
#ifdef HAVE_LZMA
struct LZMAFILE {
FILE* file;
@@ -2092,17 +2091,9 @@ public:
}
else
{
- uint64_t const memlimit = UINT64_MAX;
- if (compressor.Name == "xz")
- {
- if (lzma_auto_decoder(&lzma->stream, memlimit, 0) != LZMA_OK)
- return false;
- }
- else
- {
- if (lzma_alone_decoder(&lzma->stream, memlimit) != LZMA_OK)
- return false;
- }
+ uint64_t constexpr memlimit = 1024 * 1024 * 500;
+ if (lzma_auto_decoder(&lzma->stream, memlimit, 0) != LZMA_OK)
+ return false;
lzma->compressing = false;
}
return true;
diff --git a/apt-pkg/contrib/gpgv.cc b/apt-pkg/contrib/gpgv.cc
index 28f3150c3..3368ece84 100644
--- a/apt-pkg/contrib/gpgv.cc
+++ b/apt-pkg/contrib/gpgv.cc
@@ -121,21 +121,6 @@ static bool operator!=(LineBuffer const &buf, APT::StringView const exp) noexcep
And as a cherry on the cake, we use our apt-key wrapper to do part
of the lifting in regards to merging keyrings. Fun for the whole family.
*/
-static bool iovprintf(std::ostream &out, const char *format,
- va_list &args, ssize_t &size) {
- auto S = make_unique_char(malloc(size));
- ssize_t const n = vsnprintf(S.get(), size, format, args);
- if (n > -1 && n < size) {
- out << S.get();
- return true;
- } else {
- if (n > -1)
- size = n + 1;
- else
- size *= 2;
- }
- return false;
-}
static void APT_PRINTF(4) apt_error(std::ostream &outterm, int const statusfd, int fd[2], const char *format, ...)
{
std::ostringstream outstr;
diff --git a/apt-pkg/contrib/mmap.cc b/apt-pkg/contrib/mmap.cc
index 020491172..642e20473 100644
--- a/apt-pkg/contrib/mmap.cc
+++ b/apt-pkg/contrib/mmap.cc
@@ -393,7 +393,7 @@ unsigned long DynamicMMap::Allocate(unsigned long ItemSize)
bool const newError = _error->PendingError();
_error->MergeWithStack();
if (Pools != oldPools)
- I += Pools - oldPools;
+ I = Pools + (I - oldPools);
// Does the allocation failed ?
if (Result == 0 && newError)
diff --git a/apt-pkg/contrib/string_view.h b/apt-pkg/contrib/string_view.h
index 05aad3327..04f6ff115 100644
--- a/apt-pkg/contrib/string_view.h
+++ b/apt-pkg/contrib/string_view.h
@@ -39,6 +39,10 @@ public:
StringView(const char *data) : data_(data), size_(strlen(data)) {}
StringView(std::string const & str): data_(str.data()), size_(str.size()) {}
+ /* Modifiers */
+ void remove_prefix(size_t n) { data_ += n; size_ -= n; }
+ void remove_suffix(size_t n) { size_ -= n; }
+ void clear() { size_ = 0; }
/* Viewers */
constexpr StringView substr(size_t pos, size_t n = npos) const {
@@ -76,6 +80,28 @@ public:
return found - data_;
}
+ size_t find(APT::StringView const needle) const {
+ if (needle.empty())
+ return npos;
+ if (needle.length() == 1)
+ return find(*needle.data());
+ size_t found = 0;
+ while ((found = find(*needle.data(), found)) != npos) {
+ if (compare(found, needle.length(), needle) == 0)
+ return found;
+ ++found;
+ }
+ return found;
+ }
+ size_t find(APT::StringView const needle, size_t pos) const {
+ if (pos == 0)
+ return find(needle);
+ size_t const found = substr(pos).find(needle);
+ if (found == npos)
+ return npos;
+ return pos + found;
+ }
+
/* Conversions */
std::string to_string() const {
return std::string(data_, size_);
diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc
index bd4856526..3a0a6eaa3 100644
--- a/apt-pkg/contrib/strutl.cc
+++ b/apt-pkg/contrib/strutl.cc
@@ -23,8 +23,10 @@
#include <algorithm>
#include <array>
#include <iomanip>
+#include <limits>
#include <locale>
#include <sstream>
+#include <memory>
#include <sstream>
#include <string>
#include <vector>
@@ -310,11 +312,11 @@ bool ParseQuoteWord(const char *&String,string &Res)
}
// Now de-quote characters
- char Buffer[1024];
+ Res.clear();
+ Res.reserve(C - String);
char Tmp[3];
const char *Start = String;
- char *I;
- for (I = Buffer; I < Buffer + sizeof(Buffer) && Start != C; I++)
+ while (Start != C)
{
if (*Start == '%' && Start + 2 < C &&
isxdigit(Start[1]) && isxdigit(Start[2]))
@@ -322,19 +324,15 @@ bool ParseQuoteWord(const char *&String,string &Res)
Tmp[0] = Start[1];
Tmp[1] = Start[2];
Tmp[2] = 0;
- *I = (char)strtol(Tmp,0,16);
+ Res.push_back(static_cast<char>(strtol(Tmp, 0, 16)));
Start += 3;
continue;
}
if (*Start != '"')
- *I = *Start;
- else
- I--;
- Start++;
+ Res.push_back(*Start);
+ ++Start;
}
- *I = 0;
- Res = Buffer;
-
+
// Skip ending white space
for (; isspace(*C) != 0; C++)
;
@@ -354,33 +352,28 @@ bool ParseCWord(const char *&String,string &Res)
;
if (*C == 0)
return false;
-
- char Buffer[1024];
- char *Buf = Buffer;
- if (strlen(String) >= sizeof(Buffer))
- return false;
-
- for (; *C != 0; C++)
+
+ Res.clear();
+ Res.reserve(strlen(String));
+ for (; *C != 0; ++C)
{
if (*C == '"')
{
for (C++; *C != 0 && *C != '"'; C++)
- *Buf++ = *C;
-
+ Res.push_back(*C);
+
if (*C == 0)
return false;
-
+
continue;
- }
-
+ }
+
if (C != String && isspace(*C) != 0 && isspace(C[-1]) != 0)
continue;
if (isspace(*C) == 0)
return false;
- *Buf++ = ' ';
+ Res.push_back(' ');
}
- *Buf = 0;
- Res = Buffer;
String = C;
return true;
}
@@ -597,7 +590,7 @@ string Base64Encode(const string &S)
base64. */
for (string::const_iterator I = S.begin(); I < S.end(); I += 3)
{
- char Bits[3] = {0,0,0};
+ uint8_t Bits[3] = {0,0,0};
Bits[0] = I[0];
if (I + 1 < S.end())
Bits[1] = I[1];
@@ -1148,34 +1141,24 @@ bool FTPMDTMStrToTime(const char* const str,time_t &time)
/*}}}*/
// StrToNum - Convert a fixed length string to a number /*{{{*/
// ---------------------------------------------------------------------
-/* This is used in decoding the crazy fixed length string headers in
+/* This is used in decoding the crazy fixed length string headers in
tar and ar files. */
bool StrToNum(const char *Str,unsigned long &Res,unsigned Len,unsigned Base)
{
- char S[30];
- if (Len >= sizeof(S))
+ unsigned long long BigRes;
+ if (not StrToNum(Str, BigRes, Len, Base))
return false;
- memcpy(S,Str,Len);
- S[Len] = 0;
-
- // All spaces is a zero
- Res = 0;
- unsigned I;
- for (I = 0; S[I] == ' '; I++);
- if (S[I] == 0)
- return true;
-
- char *End;
- Res = strtoul(S,&End,Base);
- if (End == S)
+
+ if (std::numeric_limits<unsigned long>::max() < BigRes)
return false;
-
+
+ Res = BigRes;
return true;
}
/*}}}*/
// StrToNum - Convert a fixed length string to a number /*{{{*/
// ---------------------------------------------------------------------
-/* This is used in decoding the crazy fixed length string headers in
+/* This is used in decoding the crazy fixed length string headers in
tar and ar files. */
bool StrToNum(const char *Str,unsigned long long &Res,unsigned Len,unsigned Base)
{
@@ -1184,20 +1167,20 @@ bool StrToNum(const char *Str,unsigned long long &Res,unsigned Len,unsigned Base
return false;
memcpy(S,Str,Len);
S[Len] = 0;
-
+
// All spaces is a zero
Res = 0;
unsigned I;
- for (I = 0; S[I] == ' '; I++);
+ for (I = 0; S[I] == ' '; ++I);
if (S[I] == 0)
return true;
-
+ if (S[I] == '-')
+ return false;
+
char *End;
+ errno = 0;
Res = strtoull(S,&End,Base);
- if (End == S)
- return false;
-
- return true;
+ return not (End == S || errno != 0);
}
/*}}}*/
@@ -1432,13 +1415,12 @@ unsigned long RegexChoice(RxChoiceList *Rxs,const char **ListBegin,
// ---------------------------------------------------------------------
/* This is used to make the internationalization strings easier to translate
and to allow reordering of parameters */
-static bool iovprintf(ostream &out, const char *format,
+bool iovprintf(std::ostream &out, const char *format,
va_list &args, ssize_t &size) {
- char *S = (char*)malloc(size);
- ssize_t const n = vsnprintf(S, size, format, args);
+ auto S = std::unique_ptr<char,decltype(&free)>{static_cast<char*>(malloc(size)), &free};
+ ssize_t const n = vsnprintf(S.get(), size, format, args);
if (n > -1 && n < size) {
- out << S;
- free(S);
+ out << S.get();
return true;
} else {
if (n > -1)
@@ -1446,7 +1428,6 @@ static bool iovprintf(ostream &out, const char *format,
else
size *= 2;
}
- free(S);
return false;
}
void ioprintf(ostream &out,const char *format,...)
@@ -1611,22 +1592,26 @@ string DeEscapeString(const string &input)
switch (*it)
{
case '0':
- if (it + 2 <= input.end()) {
+ if (it + 2 < input.end()) {
tmp[0] = it[1];
tmp[1] = it[2];
tmp[2] = 0;
output += (char)strtol(tmp, 0, 8);
it += 2;
- }
+ } else {
+ // FIXME: raise exception here?
+ }
break;
case 'x':
- if (it + 2 <= input.end()) {
+ if (it + 2 < input.end()) {
tmp[0] = it[1];
tmp[1] = it[2];
tmp[2] = 0;
output += (char)strtol(tmp, 0, 16);
it += 2;
- }
+ } else {
+ // FIXME: raise exception here?
+ }
break;
default:
// FIXME: raise exception here?
diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h
index c25c6208a..b6e6bfdce 100644
--- a/apt-pkg/contrib/strutl.h
+++ b/apt-pkg/contrib/strutl.h
@@ -42,7 +42,7 @@ namespace APT {
APT_PUBLIC bool UTF8ToCodeset(const char *codeset, const std::string &orig, std::string *dest);
APT_PUBLIC char *_strstrip(char *String);
APT_PUBLIC char *_strrstrip(char *String); // right strip only
-APT_PUBLIC char *_strtabexpand(char *String,size_t Len);
+APT_DEPRECATED_MSG("Use SubstVar to avoid memory headaches") APT_PUBLIC char *_strtabexpand(char *String,size_t Len);
APT_PUBLIC bool ParseQuoteWord(const char *&String,std::string &Res);
APT_PUBLIC bool ParseCWord(const char *&String,std::string &Res);
APT_PUBLIC std::string QuoteString(const std::string &Str,const char *Bad);
@@ -117,6 +117,8 @@ APT_PUBLIC std::vector<std::string> StringSplit(std::string const &input,
std::string const &sep,
unsigned int maxsplit=std::numeric_limits<unsigned int>::max()) APT_PURE;
+
+APT_HIDDEN bool iovprintf(std::ostream &out, const char *format, va_list &args, ssize_t &size);
APT_PUBLIC void ioprintf(std::ostream &out,const char *format,...) APT_PRINTF(2);
APT_PUBLIC void strprintf(std::string &out,const char *format,...) APT_PRINTF(2);
APT_PUBLIC char *safe_snprintf(char *Buffer,char *End,const char *Format,...) APT_PRINTF(3);