Commit 12860515 authored by Julian Helfferich's avatar Julian Helfferich

Fix Coverity #76255: Calling risky function

When loading a plain text replay file, fscanf() was used. The use of
this function is discouraged as it can lead to buffer overflows if the
string read is larger than the reserved buffer.

Now, the C-style functions are replaced with their C++ equivalents.
This means the data is read from an ifstream and stored to a string via
an istringstream.
parent 0a4622ce
......@@ -11,6 +11,7 @@
Q_LOGGING_CATEGORY(KBGeneral, "KBlocks.General")
Q_LOGGING_CATEGORY(KBGraphics, "KBlocks.Graphics")
Q_LOGGING_CATEGORY(KBReplay, "KBlocks.Replay")
Q_LOGGING_CATEGORY(KBSound, "KBlocks.Sound")
const char *KBlocksRecordText[RecordDataType_Max_Count] = {
......
......@@ -14,6 +14,7 @@
#include <QLoggingCategory>
Q_DECLARE_LOGGING_CATEGORY(KBGeneral)
Q_DECLARE_LOGGING_CATEGORY(KBGraphics)
Q_DECLARE_LOGGING_CATEGORY(KBReplay)
Q_DECLARE_LOGGING_CATEGORY(KBSound)
#define PREPARE_AREA_WIDTH 5
......
......@@ -9,27 +9,50 @@
***************************************************************************/
#include "KBlocksGameReplayer.h"
#include <sstream>
#include <string>
#include "KBlocksDefine.h"
KBlocksGameReplayer::KBlocksGameReplayer(const char *fileName, bool isBinaryMode)
{
// Map data types to strings for reading text file
for (int i = 0; i < RecordDataType_Max_Count; ++i) {
mRTMap[ KBlocksRecordText[i] ] = i;
}
mRTMap[string("MaxCount")] = -1;
FILE *pFile = fopen(fileName, "r");
// Set default variables in case loading the file fails
mGameCount = 0;
mGameSeed = 0;
mSameSeed = false;
mStepLength = 1;
if (!pFile) {
mGameCount = 0;
mGameSeed = 0;
mSameSeed = false;
mStepLength = 1;
// Open replay file
std::ifstream replayFile;
if (isBinaryMode) {
replayFile.open(fileName, std::ios::binary);
} else {
replayFile.open(fileName);
}
// Check that replay file was opened successfully
if (!replayFile.is_open()) {
qCWarning(KBReplay) << "Unable to open file " << fileName;
return;
}
if (isBinaryMode) {
loadBinary(pFile);
loadBinary(replayFile);
} else {
loadText(pFile);
loadText(replayFile);
}
// Check that more than two Replay steps have been loaded
// The two first steps set the required variables.
if (mReplayList.size() < 2) {
qCWarning(KBReplay) << "Problem loading replay file" << fileName;
return;
}
mGameCount = mReplayList.front().value;
......@@ -38,9 +61,7 @@ KBlocksGameReplayer::KBlocksGameReplayer(const char *fileName, bool isBinaryMode
mSameSeed = (mReplayList.front().index == 1);
mReplayList.pop_front();
mStepLength = 1;
fclose(pFile);
replayFile.close();
}
KBlocksGameReplayer::~KBlocksGameReplayer()
......@@ -96,48 +117,54 @@ bool KBlocksGameReplayer::getNextRecords(vector<KBlocksReplayData> *data)
return true;
}
void KBlocksGameReplayer::loadText(FILE *pFile)
void KBlocksGameReplayer::loadText(std::ifstream &replayFile)
{
int count = 0;
char tmpString[256];
std::string line;
std::istringstream inStream;
std::string tmpString;
KBlocksReplayData tmpData;
mReplayList.clear();
while (1) {
count = fscanf(pFile, "%d %s %d %d", &(tmpData.time), tmpString, &(tmpData.index), &(tmpData.value));
tmpData.type = mRTMap[string(tmpString)];
if ((tmpData.type == -1) || (count != 4)) {
do {
std::getline(replayFile, line);
inStream.str(line);
inStream >> tmpData.time >> tmpString >> tmpData.index >> tmpData.value;
tmpData.type = mRTMap[tmpString];
if ((tmpData.type == -1) || inStream.fail()) {
break;
}
mReplayList.push_back(tmpData);
}
inStream.clear();
} while (!replayFile.eof());
}
void KBlocksGameReplayer::loadBinary(FILE *pFile)
void KBlocksGameReplayer::loadBinary(std::ifstream &replayFile)
{
KBlocksReplayData tmpData;
mReplayList.clear();
tmpData.time = fgetc(pFile);
tmpData.type = fgetc(pFile);
tmpData.index = fgetc(pFile);
tmpData.value = fgetc(pFile);
while (tmpData.time != EOF) {
tmpData.time = replayFile.get();
tmpData.type = replayFile.get();
tmpData.index = replayFile.get();
tmpData.value = replayFile.get();
do {
if (tmpData.type == RecordDataType_Skipped) {
int tmpTime = tmpData.time;
while (tmpData.type == RecordDataType_Skipped) {
tmpData.time = fgetc(pFile);
tmpData.type = fgetc(pFile);
tmpData.index = fgetc(pFile);
tmpData.value = fgetc(pFile);
tmpData.time = replayFile.get();
tmpData.type = replayFile.get();
tmpData.index = replayFile.get();
tmpData.value = replayFile.get();
tmpTime += tmpData.time;
}
tmpData.time = tmpTime;
}
mReplayList.push_back(tmpData);
tmpData.time = fgetc(pFile);
tmpData.type = fgetc(pFile);
tmpData.index = fgetc(pFile);
tmpData.value = fgetc(pFile);
}
tmpData.time = replayFile.get();
tmpData.type = replayFile.get();
tmpData.index = replayFile.get();
tmpData.value = replayFile.get();
} while (!replayFile.eof());
}
......@@ -12,7 +12,7 @@
#include "KBlocksDefine.h"
#include <stdio.h>
#include <fstream>
#include <string>
#include <vector>
#include <list>
......@@ -46,8 +46,8 @@ public:
bool getNextRecords(vector<KBlocksReplayData> *data);
private:
void loadText(FILE *pFile);
void loadBinary(FILE *pFile);
void loadText(std::ifstream &pFile);
void loadBinary(std::ifstream &pFile);
private:
int mGameCount;
......
......@@ -160,7 +160,7 @@ void KBlocksRepWin::replayOneStep()
{
int tmpPieceChanged = 0;
if (!mpGameLogic->playRecordOneStep(&tmpPieceChanged)) {
printf("Finished Replay!\n");
qCDebug(KBReplay) << "Finished Replay!";
mUpdateTimer.stop();
}
if (tmpPieceChanged != 0) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment