bspatch.c
Go to the documentation of this file.
1 /* Modified by Martin Peterlin from bsdiff-4.3 to be able to patch in memory */
2 /*-
3  * Copyright 2003-2005 Colin Percival
4  * All rights reserved
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted providing that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "bspatch.h"
29 
30 #include <bzlib.h>
31 #include <stdlib.h>
32 #include <string.h>
33 
35 
36 static int64_t offtin(const uint8_t* buf) {
37  int64_t y;
38 
39  y = buf[7] & 0x7F;
40  y = y * 256;
41  y += buf[6];
42  y = y * 256;
43  y += buf[5];
44  y = y * 256;
45  y += buf[4];
46  y = y * 256;
47  y += buf[3];
48  y = y * 256;
49  y += buf[2];
50  y = y * 256;
51  y += buf[1];
52  y = y * 256;
53  y += buf[0];
54 
55  if(buf[7] & 0x80) y = -y;
56 
57  return y;
58 }
59 
60 int64_t bspatch_mem_get_newsize(const uint8_t* patchfile_bin, const int64_t patchfile_size) {
61  uint8_t header[32];
62 
63  /* Read header */
64  if(patchfile_size < 32) return -1;
65  memcpy(header, patchfile_bin, 32);
66 
67  /* Check for appropriate magic */
68  if(memcmp(header, "BSDIFF40", 8) != 0) return -1;
69 
70  int64_t newsize = offtin(header + 24);
71  if(newsize < 0) return -1;
72  return newsize;
73 }
74 
75 int bspatch_mem(const uint8_t* oldfile_bin, const int64_t oldfile_size, const uint8_t* patchfile_bin, const int64_t patchfile_size, uint8_t* newfile_bin) {
76  int64_t oldsize = oldfile_size;
77  int64_t newsize;
78  int64_t bzctrllen, bzdatalen;
79  uint8_t header[32];
80  const uint8_t* old = oldfile_bin;
81  uint8_t* new = newfile_bin;
82  int64_t oldpos, newpos;
83  int64_t ctrl[3];
84  int64_t i;
85  int64_t cpOffset, dpOffset, epOffset;
86  int error = 0;
87 
88  /*
89  File format:
90  0 8 "BSDIFF40"
91  8 8 X
92  16 8 Y
93  24 8 sizeof(newfile)
94  32 X bzip2(control block)
95  32+X Y bzip2(diff block)
96  32+X+Y ??? bzip2(extra block)
97  with control block a set of triples (x,y,z) meaning "add x bytes
98  from oldfile to x bytes from the diff block; copy y bytes from the
99  extra block; seek forwards in oldfile by z bytes".
100  */
101 
102  /* Read header */
103  if(patchfile_size < 32) return -1;
104  memcpy(header, patchfile_bin, 32);
105 
106  /* Check for appropriate magic */
107  if(memcmp(header, "BSDIFF40", 8) != 0) return -1;
108 
109  /* Read lengths from header */
110  bzctrllen = offtin(header + 8);
111  bzdatalen = offtin(header + 16);
112  newsize = offtin(header + 24);
113  if((bzctrllen < 0) || (bzdatalen < 0) || (newsize < 0)) return -1;
114 
115  /* Close patch file and re-open it via libbzip2 at the right places */
116  cpOffset = sizeof(header);
117  dpOffset = sizeof(header) + bzctrllen;
118  epOffset = sizeof(header) + bzctrllen + bzdatalen;
119 
120  /* Decompress control block, diff block and extra block */
121 
122  int64_t block_offset_bz2[NUM_BLOCKS] = {cpOffset, dpOffset, epOffset};
123  int64_t block_size_bz2[NUM_BLOCKS] = {bzctrllen, bzdatalen, patchfile_size - epOffset};
124  uint8_t* p_decompressed_block_original[NUM_BLOCKS] = {NULL, NULL, NULL};
125  uint8_t* p_decompressed_block[NUM_BLOCKS] = {NULL, NULL, NULL};
126  uint8_t* p_decompressed_block_end[NUM_BLOCKS] = {NULL, NULL, NULL};
127 
128  for(int i = 0; i < NUM_BLOCKS; i++) {
129  unsigned int decompressed_size = (unsigned int)newsize * 4;
130  p_decompressed_block_original[i] = malloc(decompressed_size); // reserve enough memory
131 
132  int ret = 0;
133  if((ret = BZ2_bzBuffToBuffDecompress(
134  (char*)p_decompressed_block_original[i], &decompressed_size, (char*)patchfile_bin + block_offset_bz2[i], (unsigned int)block_size_bz2[i], 0, 0))
135  != BZ_OK) {
136  (void)ret;
137  error = -1;
138  break;
139  }
140 
141  // realloc pointer (and save if changes)
142  p_decompressed_block_original[i] = realloc(p_decompressed_block_original[i], decompressed_size); // resize memory to not waste additional space
143 
144  // Create current and end pointer
145  p_decompressed_block[i] = p_decompressed_block_original[i];
146  p_decompressed_block_end[i] = p_decompressed_block[i] + decompressed_size;
147  }
148  if(error) {
149  for(int i = 0; i < NUM_BLOCKS; i++) {
150  free(p_decompressed_block_original[i]);
151  }
152  return -1;
153  }
154 
155  // Patch algorithm
156 
157  oldpos = 0;
158  newpos = 0;
159  while(newpos < newsize) {
160  /* Read control data */
161  for(i = 0; i <= 2; i++) {
162  // if end of control data
163  if(p_decompressed_block[CONTROL_BLOCK] + 8 > p_decompressed_block_end[CONTROL_BLOCK]) {
164  error = -1;
165  break;
166  }
167 
168  // read from control block
169  ctrl[i] = offtin(p_decompressed_block[CONTROL_BLOCK]);
170 
171  // move pointer forward
172  p_decompressed_block[CONTROL_BLOCK] += 8;
173  };
174  if(error) break;
175 
176  /* Sanity-check */
177  if(newpos + ctrl[0] > newsize) {
178  for(int i = 0; i < NUM_BLOCKS; i++) {
179  free(p_decompressed_block_original[i]);
180  }
181  return -1;
182  }
183 
184  /* Read diff string */
185  if(p_decompressed_block[DIFF_BLOCK] + ctrl[0] > p_decompressed_block_end[DIFF_BLOCK]) {
186  error = -1;
187  break;
188  }
189  memcpy(new + newpos, p_decompressed_block[DIFF_BLOCK], ctrl[0]);
190  p_decompressed_block[DIFF_BLOCK] += ctrl[0];
191 
192  /* Add old data to diff string */
193  for(i = 0; i < ctrl[0]; i++) {
194  if((oldpos + i >= 0) && (oldpos + i < oldsize)) {
195  new[newpos + i] += old[oldpos + i];
196  }
197  }
198 
199  /* Adjust pointers */
200  newpos += ctrl[0];
201  oldpos += ctrl[0];
202 
203  /* Sanity-check */
204  if(newpos + ctrl[1] > newsize) {
205  error = -1;
206  break;
207  }
208 
209  /* Read extra string */
210  if(p_decompressed_block[EXTRA_BLOCK] + ctrl[1] > p_decompressed_block_end[EXTRA_BLOCK]) {
211  for(int i = 0; i < NUM_BLOCKS; i++) {
212  free(p_decompressed_block_original[i]);
213  }
214  return -1;
215  }
216  memcpy(new + newpos, p_decompressed_block[EXTRA_BLOCK], ctrl[1]);
217  p_decompressed_block[EXTRA_BLOCK] += ctrl[1];
218 
219  /* Adjust pointers */
220  newpos += ctrl[1];
221  oldpos += ctrl[2];
222  };
223 
224  /* Clean up the bzip2 reads */
225  for(int i = 0; i < NUM_BLOCKS; i++) {
226  free(p_decompressed_block_original[i]);
227  }
228 
229  return error;
230 }
block_type
block_type
Definition: bspatch.c:34
bspatch_mem_get_newsize
int64_t bspatch_mem_get_newsize(const uint8_t *patchfile_bin, const int64_t patchfile_size)
Definition: bspatch.c:60
CONTROL_BLOCK
@ CONTROL_BLOCK
Definition: bspatch.c:34
bspatch_mem
int bspatch_mem(const uint8_t *oldfile_bin, const int64_t oldfile_size, const uint8_t *patchfile_bin, const int64_t patchfile_size, uint8_t *newfile_bin)
Definition: bspatch.c:75
NUM_BLOCKS
@ NUM_BLOCKS
Definition: bspatch.c:34
dai::logger::error
void error(const FormatString &fmt, Args &&...args)
Definition: Logging.hpp:90
offtin
static int64_t offtin(const uint8_t *buf)
Definition: bspatch.c:36
EXTRA_BLOCK
@ EXTRA_BLOCK
Definition: bspatch.c:34
DIFF_BLOCK
@ DIFF_BLOCK
Definition: bspatch.c:34
bspatch.h
dai::utility::buf
const typedef std::vector< std::uint8_t > buf
Definition: H26xParsers.cpp:40


depthai
Author(s): Martin Peterlin
autogenerated on Sat Mar 22 2025 02:58:18