2726: Only send valid UTF-8 over the network r=def- a=heinrich5991



Co-authored-by: heinrich5991 <heinrich5991@gmail.com>
This commit is contained in:
bors[bot] 2020-09-03 17:13:10 +00:00 committed by GitHub
commit e40e1866e2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 89 additions and 25 deletions

View file

@ -2083,6 +2083,7 @@ if(GTEST_FOUND OR DOWNLOAD_GTEST)
json.cpp json.cpp
mapbugs.cpp mapbugs.cpp
name_ban.cpp name_ban.cpp
packer.cpp
prng.cpp prng.cpp
str.cpp str.cpp
strip_path_and_extension.cpp strip_path_and_extension.cpp

View file

@ -33,37 +33,35 @@ void CPacker::AddString(const char *pStr, int Limit)
if(m_Error) if(m_Error)
return; return;
// if(Limit <= 0)
if(Limit > 0)
{ {
Limit = PACKER_BUFFER_SIZE;
}
while(*pStr && Limit != 0) while(*pStr && Limit != 0)
{ {
*m_pCurrent++ = *pStr++; int Codepoint = str_utf8_decode(&pStr);
Limit--; if(Codepoint == -1)
{
if(m_pCurrent >= m_pEnd) Codepoint = 0xfffd; // Unicode replacement character.
}
char aGarbage[4];
int Length = str_utf8_encode(aGarbage, Codepoint);
if(Limit < Length)
{
break;
}
// Ensure space for the null termination.
if(m_pEnd - m_pCurrent < Length + 1)
{ {
m_Error = 1; m_Error = 1;
break; break;
} }
Length = str_utf8_encode((char *)m_pCurrent, Codepoint);
m_pCurrent += Length;
Limit -= Length;
} }
*m_pCurrent++ = 0; *m_pCurrent++ = 0;
} }
else
{
while(*pStr)
{
*m_pCurrent++ = *pStr++;
if(m_pCurrent >= m_pEnd)
{
m_Error = 1;
break;
}
}
*m_pCurrent++ = 0;
}
}
void CPacker::AddRaw(const void *pData, int Size) void CPacker::AddRaw(const void *pData, int Size)
{ {

View file

@ -7,11 +7,12 @@
class CPacker class CPacker
{ {
public:
enum enum
{ {
PACKER_BUFFER_SIZE=1024*2 PACKER_BUFFER_SIZE=1024*2
}; };
private:
unsigned char m_aBuffer[PACKER_BUFFER_SIZE]; unsigned char m_aBuffer[PACKER_BUFFER_SIZE];
unsigned char *m_pCurrent; unsigned char *m_pCurrent;
unsigned char *m_pEnd; unsigned char *m_pEnd;

64
src/test/packer.cpp Normal file
View file

@ -0,0 +1,64 @@
#include "test.h"
#include <gtest/gtest.h>
#include <base/system.h>
#include <engine/shared/packer.h>
// pExpected is NULL if an error is expected
static void ExpectAddString5(const char *pString, int Limit, const char *pExpected)
{
static char ZEROS[CPacker::PACKER_BUFFER_SIZE] = {0};
static const int OFFSET = CPacker::PACKER_BUFFER_SIZE - 5;
CPacker Packer;
Packer.Reset();
Packer.AddRaw(ZEROS, OFFSET);
Packer.AddString(pString, Limit);
EXPECT_EQ(pExpected == 0, Packer.Error());
if(pExpected)
{
// Include null termination.
int ExpectedLength = str_length(pExpected) + 1;
EXPECT_EQ(ExpectedLength, Packer.Size() - OFFSET);
if(ExpectedLength == Packer.Size() - OFFSET)
{
EXPECT_STREQ(pExpected, (const char *)Packer.Data() + OFFSET);
}
}
}
TEST(Packer, AddString)
{
ExpectAddString5("", 0, "");
ExpectAddString5("a", 0, "a");
ExpectAddString5("abcd", 0, "abcd");
ExpectAddString5("abcde", 0, 0);
}
TEST(Packer, AddStringLimit)
{
ExpectAddString5("", 1, "");
ExpectAddString5("a", 1, "a");
ExpectAddString5("aa", 1, "a");
ExpectAddString5("ä", 1, "");
ExpectAddString5("", 10, "");
ExpectAddString5("a", 10, "a");
ExpectAddString5("abcd", 10, "abcd");
ExpectAddString5("abcde", 10, 0);
ExpectAddString5("äöü", 5, "äö");
ExpectAddString5("äöü", 6, 0);
}
TEST(Packer, AddStringBroken)
{
ExpectAddString5("\x80", 0, "<EFBFBD>");
ExpectAddString5("\x80\x80", 0, 0);
ExpectAddString5("a\x80", 0, "a<EFBFBD>");
ExpectAddString5("\x80""a", 0, "<EFBFBD>a");
ExpectAddString5("\x80", 1, "");
ExpectAddString5("\x80\x80", 3, "<EFBFBD>");
ExpectAddString5("\x80\x80", 5, "<EFBFBD>");
ExpectAddString5("\x80\x80", 6, 0);
}