Merge pull request #227 from RElesgoe/master
Possible crash at userlog_read() when an argument is a null pointer
This commit is contained in:
commit
81c35b65f0
2 changed files with 80 additions and 68 deletions
|
@ -17,12 +17,14 @@
|
|||
*/
|
||||
#include "common/setup_before.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include "compat/strcasecmp.h"
|
||||
#include "compat/pdir.h"
|
||||
|
@ -153,80 +155,81 @@ namespace pvpgn
|
|||
}
|
||||
|
||||
// read "count" lines from the end starting from "startline"
|
||||
extern std::map<long, char*> userlog_read(const char * username, long startline, const char * search_substr)
|
||||
extern std::map<long, char*> userlog_read(const char* username, long startline, const char* search_substr)
|
||||
{
|
||||
std::map<long, char*> lines;
|
||||
if (!username)
|
||||
throw std::exception("username is a nullptr");
|
||||
|
||||
FILE* fp = std::fopen(userlog_filename(username), "r");
|
||||
if (!fp)
|
||||
throw std::exception("Could not open userlog");
|
||||
|
||||
// set position to the end of file
|
||||
std::fseek(fp, 0, SEEK_END);
|
||||
|
||||
long pos = std::ftell(fp);
|
||||
char c = {}, prev_c = {};
|
||||
std::map<long, char*> lines;
|
||||
long linecount = 0;
|
||||
char line[MAX_MESSAGE_LEN+1];
|
||||
char line[MAX_MESSAGE_LEN + 1] = {};
|
||||
int linepos = 0;
|
||||
|
||||
char c, prev_c = 0;
|
||||
long pos;
|
||||
|
||||
size_t search_substrlen = std::strlen(search_substr);
|
||||
|
||||
char * filename = userlog_filename(username);
|
||||
if (FILE *fp = fopen(filename, "r"))
|
||||
// read file in reverse, byte by byte
|
||||
do
|
||||
{
|
||||
// set position to the end of file
|
||||
fseek(fp, 0, SEEK_END);
|
||||
pos = ftell(fp);
|
||||
pos--;
|
||||
std::fseek(fp, pos, SEEK_SET);
|
||||
c = std::fgetc(fp);
|
||||
|
||||
// read file reversely by byte
|
||||
do {
|
||||
pos--;
|
||||
fseek(fp, pos, SEEK_SET);
|
||||
c = fgetc(fp);
|
||||
// add char into line array
|
||||
if (c != '\n')
|
||||
line[linepos] = c;
|
||||
|
||||
// add char into line array
|
||||
if (c != '\n')
|
||||
line[linepos] = c;
|
||||
|
||||
// end of line (or start of file)
|
||||
if ((c == '\n' && c != prev_c) || pos == -1)
|
||||
// end of line (or start of file)
|
||||
if ((c == '\n' && c != prev_c) || pos == -1)
|
||||
{
|
||||
// hack for large lines (instead we will receive cut line without start symbols)
|
||||
if (linepos == MAX_MESSAGE_LEN)
|
||||
{
|
||||
// hack for large lines (instead we will receive cut line without start symbols)
|
||||
if (linepos == MAX_MESSAGE_LEN)
|
||||
{
|
||||
// return carriage to read whole line to(from) start
|
||||
pos = pos + MAX_MESSAGE_LEN;
|
||||
linepos = 0;
|
||||
}
|
||||
if (linepos > 0)
|
||||
{
|
||||
line[linepos] = '\0'; // set end of string
|
||||
strreverse(line);
|
||||
|
||||
linepos = 0; // reset position inside line
|
||||
|
||||
linecount++;
|
||||
if (linecount >= startline)
|
||||
{
|
||||
if (search_substr && search_substrlen > 0)
|
||||
{
|
||||
if (find_substr(line, search_substr))
|
||||
lines[linecount] = xstrdup(line);
|
||||
}
|
||||
else
|
||||
{
|
||||
lines[linecount] = xstrdup(line);
|
||||
}
|
||||
}
|
||||
|
||||
// limitation of results
|
||||
if (lines.size() >= userlog_max_output_lines)
|
||||
break;
|
||||
}
|
||||
// return carriage to read whole line to(from) start
|
||||
pos = pos + MAX_MESSAGE_LEN;
|
||||
linepos = 0;
|
||||
}
|
||||
prev_c = c;
|
||||
if (c != '\n' && linepos < MAX_MESSAGE_LEN)
|
||||
linepos++;
|
||||
|
||||
} while (c != EOF);
|
||||
if (linepos > 0)
|
||||
{
|
||||
line[linepos] = '\0'; // set end of string
|
||||
strreverse(line);
|
||||
|
||||
linepos = 0; // reset position inside line
|
||||
|
||||
linecount++;
|
||||
if (linecount >= startline)
|
||||
{
|
||||
if (search_substr && std::strlen(search_substr) > 0)
|
||||
{
|
||||
if (find_substr(line, search_substr))
|
||||
lines[linecount] = xstrdup(line);
|
||||
}
|
||||
else
|
||||
{
|
||||
lines[linecount] = xstrdup(line);
|
||||
}
|
||||
}
|
||||
|
||||
// limitation of results
|
||||
if (lines.size() >= userlog_max_output_lines)
|
||||
break;
|
||||
}
|
||||
}
|
||||
prev_c = c;
|
||||
if (c != '\n' && linepos < MAX_MESSAGE_LEN)
|
||||
linepos++;
|
||||
|
||||
} while (c != EOF);
|
||||
|
||||
std::fclose(fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
|
@ -306,7 +309,15 @@ namespace pvpgn
|
|||
if (!args[3].empty())
|
||||
startline = atoi(args[3].c_str());
|
||||
|
||||
lines = userlog_read(username, startline);
|
||||
try
|
||||
{
|
||||
lines = userlog_read(username, startline);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
message_send_text(c, message_type_error, c, "Could not read user log");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// find
|
||||
else if (subcommand[0] == 'f')
|
||||
|
|
|
@ -20,9 +20,10 @@
|
|||
#ifndef INCLUDED_USERLOGS_PROTOS
|
||||
#define INCLUDED_USERLOGS_PROTOS
|
||||
|
||||
#define JUST_NEED_TYPES
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#define JUST_NEED_TYPES
|
||||
#include "connection.h"
|
||||
#undef JUST_NEED_TYPES
|
||||
|
||||
|
@ -34,7 +35,7 @@ namespace pvpgn
|
|||
extern void userlog_init();
|
||||
|
||||
extern void userlog_append(t_account * account, const char * text);
|
||||
extern std::map<long, char*> userlog_read(const char * username, long startline, const char * search_substr = NULL);
|
||||
extern std::map<long, char*> userlog_read(const char* username, long startline, const char* search_substr = nullptr);
|
||||
extern std::map<long, char*> userlog_find_text(const char * username, const char * search_substr, long startline);
|
||||
extern char * userlog_filename(const char * username, bool force_create_path = false);
|
||||
|
||||
|
|
Loading…
Reference in a new issue