Fix IPS patching

- Fix crash on applying IPS patch
- Make IPS offset rewriting work right
This commit is contained in:
Ilari Liusvaara 2011-12-12 18:21:09 +02:00
parent b8e236972a
commit 993eeb20d3

View file

@ -80,9 +80,9 @@ namespace
if(patch.size() < roffset + 3) if(patch.size() < roffset + 3)
throw std::runtime_error("Patch incomplete"); throw std::runtime_error("Patch incomplete");
uint32_t a, b, c; uint32_t a, b, c;
a = patch[roffset + 0]; a = static_cast<uint8_t>(patch[roffset + 0]);
b = patch[roffset + 1]; b = static_cast<uint8_t>(patch[roffset + 1]);
c = patch[roffset + 2]; c = static_cast<uint8_t>(patch[roffset + 2]);
uint32_t rec_off = a * 65536 + b * 256 + c; uint32_t rec_off = a * 65536 + b * 256 + c;
if(rec_off == 0x454F46) { if(rec_off == 0x454F46) {
//EOF. //EOF.
@ -91,16 +91,16 @@ namespace
} }
if(patch.size() < roffset + 5) if(patch.size() < roffset + 5)
throw std::runtime_error("Patch incomplete"); throw std::runtime_error("Patch incomplete");
a = patch[roffset + 3]; a = static_cast<uint8_t>(patch[roffset + 3]);
b = patch[roffset + 4]; b = static_cast<uint8_t>(patch[roffset + 4]);
uint32_t rec_size = a * 256 + b; uint32_t rec_size = a * 256 + b;
uint32_t rec_rlesize = 0; uint32_t rec_rlesize = 0;
uint32_t rec_rawsize = 0; uint32_t rec_rawsize = 0;
if(!rec_size) { if(!rec_size) {
if(patch.size() < roffset + 8) if(patch.size() < roffset + 8)
throw std::runtime_error("Patch incomplete"); throw std::runtime_error("Patch incomplete");
a = patch[roffset + 5]; a = static_cast<uint8_t>(patch[roffset + 5]);
b = patch[roffset + 6]; b = static_cast<uint8_t>(patch[roffset + 6]);
rec_rlesize = a * 256 + b; rec_rlesize = a * 256 + b;
rec_rawsize = 8; rec_rawsize = 8;
} else } else
@ -110,15 +110,21 @@ namespace
throw std::runtime_error("Offset exceeds IPS 16MiB limit"); throw std::runtime_error("Offset exceeds IPS 16MiB limit");
if(rec_noff < 0) { if(rec_noff < 0) {
//This operation needs to clip the start as it is out of bounds. //This operation needs to clip the start as it is out of bounds.
while(rec_size > 0 && rec_noff + rec_size <= 0) { if(rec_size) {
rec_noff++; if(rec_size > -rec_noff) {
rec_size--; rec_noff = 0;
rec_size -= -rec_noff;
} else
rec_size = 0;
} }
while(rec_rlesize > 0 && rec_noff + rec_rlesize <= 0) { if(rec_rlesize) {
rec_noff++; if(rec_rlesize > -rec_noff) {
rec_rlesize--; rec_noff = 0;
rec_rlesize -= -rec_noff;
} else
rec_rlesize = 0;
} }
if(rec_noff + rec_size + rec_rlesize <= 0) if(!rec_size && !rec_rlesize)
return std::make_pair(0, rec_rawsize); //Completely out of bounds. return std::make_pair(0, rec_rawsize); //Completely out of bounds.
} }
//Write the modified record. //Write the modified record.
@ -172,6 +178,9 @@ namespace
std::vector<char> ret; std::vector<char> ret;
ret.resize(p.size); ret.resize(p.size);
memcpy(&ret[0], p.data, p.size); memcpy(&ret[0], p.data, p.size);
//No, these can't be freed.
p.source(NULL, 0);
p.modify(NULL, 0);
return ret; return ret;
} }
} }