diff options
| author | Paul Eggert | 2014-02-13 09:23:08 -0800 |
|---|---|---|
| committer | Paul Eggert | 2014-02-13 09:23:08 -0800 |
| commit | d51c175a53de5edfa3f56daf0496755af6f913ee (patch) | |
| tree | 47a285a4ec23b206a2c07e3c7dea98b12dd6e682 /src | |
| parent | ccd5d23b0adea0aa0d8b8f1bcc4ca2630f9214a3 (diff) | |
| download | emacs-d51c175a53de5edfa3f56daf0496755af6f913ee.tar.gz emacs-d51c175a53de5edfa3f56daf0496755af6f913ee.zip | |
Fix subspace record bug on HP-UX 10.20.
* unexhp9k800.c (unexec_error): New function, to simplify the code.
(check_lseek): New function, to report lseek errors.
(save_data_space, update_file_ptrs, read_header, write_header)
(copy_file, copy_rest, unexec): Use these news functions.
(update_file_ptrs): Don't assume wraparound behavior when
converting a large size_t value to off_t.
Fixes: debbugs:16717
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 10 | ||||
| -rw-r--r-- | src/unexhp9k800.c | 82 |
2 files changed, 58 insertions, 34 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 72ed95909e4..2be308f50f9 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,13 @@ | |||
| 1 | 2014-02-13 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Fix subspace record bug on HP-UX 10.20 (Bug#16717). | ||
| 4 | * unexhp9k800.c (unexec_error): New function, to simplify the code. | ||
| 5 | (check_lseek): New function, to report lseek errors. | ||
| 6 | (save_data_space, update_file_ptrs, read_header, write_header) | ||
| 7 | (copy_file, copy_rest, unexec): Use these news functions. | ||
| 8 | (update_file_ptrs): Don't assume wraparound behavior when | ||
| 9 | converting a large size_t value to off_t. | ||
| 10 | |||
| 1 | 2014-02-13 Dmitry Antipov <dmantipov@yandex.ru> | 11 | 2014-02-13 Dmitry Antipov <dmantipov@yandex.ru> |
| 2 | 12 | ||
| 3 | * composite.c (fill_gstring_header): Pass positions as C integers | 13 | * composite.c (fill_gstring_header): Pass positions as C integers |
diff --git a/src/unexhp9k800.c b/src/unexhp9k800.c index bee2517307a..55db8071b76 100644 --- a/src/unexhp9k800.c +++ b/src/unexhp9k800.c | |||
| @@ -74,6 +74,22 @@ run_time_remap (char *ignored) | |||
| 74 | #define roundup(x,n) (((x) + ((n) - 1)) & ~((n) - 1)) /* n is power of 2 */ | 74 | #define roundup(x,n) (((x) + ((n) - 1)) & ~((n) - 1)) /* n is power of 2 */ |
| 75 | #define min(x,y) (((x) < (y)) ? (x) : (y)) | 75 | #define min(x,y) (((x) < (y)) ? (x) : (y)) |
| 76 | 76 | ||
| 77 | /* Report a fatal error and exit. */ | ||
| 78 | static _Noreturn void | ||
| 79 | unexec_error (char const *msg) | ||
| 80 | { | ||
| 81 | perror (msg); | ||
| 82 | exit (1); | ||
| 83 | } | ||
| 84 | |||
| 85 | /* Do an lseek and check the result. */ | ||
| 86 | static void | ||
| 87 | check_lseek (int fd, off_t offset, int whence) | ||
| 88 | { | ||
| 89 | if (lseek (fd, offset, whence) < 0) | ||
| 90 | unexec_error ("Cannot lseek"); | ||
| 91 | } | ||
| 92 | |||
| 77 | /* Save current data space in the file, update header. */ | 93 | /* Save current data space in the file, update header. */ |
| 78 | 94 | ||
| 79 | static void | 95 | static void |
| @@ -82,7 +98,7 @@ save_data_space (int file, struct header *hdr, struct som_exec_auxhdr *auxhdr, | |||
| 82 | { | 98 | { |
| 83 | /* Write the entire data space out to the file */ | 99 | /* Write the entire data space out to the file */ |
| 84 | if (write (file, auxhdr->exec_dmem, size) != size) | 100 | if (write (file, auxhdr->exec_dmem, size) != size) |
| 85 | { perror ("Can't save new data space"); exit (1); } | 101 | unexec_error ("Can't save new data space"); |
| 86 | 102 | ||
| 87 | /* Update the header to reflect the new data size */ | 103 | /* Update the header to reflect the new data size */ |
| 88 | auxhdr->exec_dsize = size; | 104 | auxhdr->exec_dsize = size; |
| @@ -115,20 +131,21 @@ update_file_ptrs (int file, struct header *hdr, struct som_exec_auxhdr *auxhdr, | |||
| 115 | update (auxhdr->exec_dfile); | 131 | update (auxhdr->exec_dfile); |
| 116 | 132 | ||
| 117 | /* Do for each subspace dictionary entry */ | 133 | /* Do for each subspace dictionary entry */ |
| 118 | lseek (file, hdr->subspace_location, 0); | 134 | check_lseek (file, hdr->subspace_location, 0); |
| 119 | for (i = 0; i < hdr->subspace_total; i++) | 135 | for (i = 0; i < hdr->subspace_total; i++) |
| 120 | { | 136 | { |
| 121 | if (read (file, &subspace, sizeof (subspace)) != sizeof (subspace)) | 137 | ptrdiff_t subspace_size = sizeof subspace; |
| 122 | { perror ("Can't read subspace record"); exit (1); } | 138 | if (read (file, &subspace, subspace_size) != subspace_size) |
| 139 | unexec_error ("Can't read subspace record"); | ||
| 123 | 140 | ||
| 124 | /* If subspace has a file location, update it */ | 141 | /* If subspace has a file location, update it */ |
| 125 | if (subspace.initialization_length > 0 | 142 | if (subspace.initialization_length > 0 |
| 126 | && subspace.file_loc_init_value > location) | 143 | && subspace.file_loc_init_value > location) |
| 127 | { | 144 | { |
| 128 | subspace.file_loc_init_value += offset; | 145 | subspace.file_loc_init_value += offset; |
| 129 | lseek (file, -sizeof (subspace), 1); | 146 | check_lseek (file, -subspace_size, 1); |
| 130 | if (write (file, &subspace, sizeof (subspace)) != sizeof (subspace)) | 147 | if (write (file, &subspace, subspace_size) != subspace_size) |
| 131 | { perror ("Can't update subspace record"); exit (1); } | 148 | unexec_error ("Can't update subspace record"); |
| 132 | } | 149 | } |
| 133 | } | 150 | } |
| 134 | 151 | ||
| @@ -144,9 +161,9 @@ read_header (int file, struct header *hdr, struct som_exec_auxhdr *auxhdr) | |||
| 144 | { | 161 | { |
| 145 | 162 | ||
| 146 | /* Read the header in */ | 163 | /* Read the header in */ |
| 147 | lseek (file, 0, 0); | 164 | check_lseek (file, 0, 0); |
| 148 | if (read (file, hdr, sizeof (*hdr)) != sizeof (*hdr)) | 165 | if (read (file, hdr, sizeof (*hdr)) != sizeof (*hdr)) |
| 149 | { perror ("Couldn't read header from a.out file"); exit (1); } | 166 | unexec_error ("Couldn't read header from a.out file"); |
| 150 | 167 | ||
| 151 | if (hdr->a_magic != EXEC_MAGIC && hdr->a_magic != SHARE_MAGIC | 168 | if (hdr->a_magic != EXEC_MAGIC && hdr->a_magic != SHARE_MAGIC |
| 152 | && hdr->a_magic != DEMAND_MAGIC) | 169 | && hdr->a_magic != DEMAND_MAGIC) |
| @@ -155,12 +172,9 @@ read_header (int file, struct header *hdr, struct som_exec_auxhdr *auxhdr) | |||
| 155 | exit (1); | 172 | exit (1); |
| 156 | } | 173 | } |
| 157 | 174 | ||
| 158 | lseek (file, hdr->aux_header_location, 0); | 175 | check_lseek (file, hdr->aux_header_location, 0); |
| 159 | if (read (file, auxhdr, sizeof (*auxhdr)) != sizeof (*auxhdr)) | 176 | if (read (file, auxhdr, sizeof (*auxhdr)) != sizeof (*auxhdr)) |
| 160 | { | 177 | unexec_error ("Couldn't read auxiliary header from a.out file"); |
| 161 | perror ("Couldn't read auxiliary header from a.out file"); | ||
| 162 | exit (1); | ||
| 163 | } | ||
| 164 | } | 178 | } |
| 165 | 179 | ||
| 166 | /* Write out the header records into an a.out file. */ | 180 | /* Write out the header records into an a.out file. */ |
| @@ -172,12 +186,12 @@ write_header (int file, struct header *hdr, struct som_exec_auxhdr *auxhdr) | |||
| 172 | hdr->checksum = calculate_checksum (hdr); | 186 | hdr->checksum = calculate_checksum (hdr); |
| 173 | 187 | ||
| 174 | /* Write the header back into the a.out file */ | 188 | /* Write the header back into the a.out file */ |
| 175 | lseek (file, 0, 0); | 189 | check_lseek (file, 0, 0); |
| 176 | if (write (file, hdr, sizeof (*hdr)) != sizeof (*hdr)) | 190 | if (write (file, hdr, sizeof (*hdr)) != sizeof (*hdr)) |
| 177 | { perror ("Couldn't write header to a.out file"); exit (1); } | 191 | unexec_error ("Couldn't write header to a.out file"); |
| 178 | lseek (file, hdr->aux_header_location, 0); | 192 | check_lseek (file, hdr->aux_header_location, 0); |
| 179 | if (write (file, auxhdr, sizeof (*auxhdr)) != sizeof (*auxhdr)) | 193 | if (write (file, auxhdr, sizeof (*auxhdr)) != sizeof (*auxhdr)) |
| 180 | { perror ("Couldn't write auxiliary header to a.out file"); exit (1); } | 194 | unexec_error ("Couldn't write auxiliary header to a.out file"); |
| 181 | } | 195 | } |
| 182 | 196 | ||
| 183 | /* Calculate the checksum of a SOM header record. */ | 197 | /* Calculate the checksum of a SOM header record. */ |
| @@ -207,9 +221,9 @@ copy_file (int old, int new, int size) | |||
| 207 | { | 221 | { |
| 208 | len = min (size, sizeof (buffer)); | 222 | len = min (size, sizeof (buffer)); |
| 209 | if (read (old, buffer, len) != len) | 223 | if (read (old, buffer, len) != len) |
| 210 | { perror ("Read failure on a.out file"); exit (1); } | 224 | unexec_error ("Read failure on a.out file"); |
| 211 | if (write (new, buffer, len) != len) | 225 | if (write (new, buffer, len) != len) |
| 212 | { perror ("Write failure in a.out file"); exit (1); } | 226 | unexec_error ("Write failure in a.out file"); |
| 213 | } | 227 | } |
| 214 | } | 228 | } |
| 215 | 229 | ||
| @@ -226,7 +240,7 @@ copy_rest (int old, int new) | |||
| 226 | if (write (new, buffer, len) != len) break; | 240 | if (write (new, buffer, len) != len) break; |
| 227 | 241 | ||
| 228 | if (len != 0) | 242 | if (len != 0) |
| 229 | { perror ("Unable to copy the rest of the file"); exit (1); } | 243 | unexec_error ("Unable to copy the rest of the file"); |
| 230 | } | 244 | } |
| 231 | 245 | ||
| 232 | #ifdef DEBUG | 246 | #ifdef DEBUG |
| @@ -268,44 +282,44 @@ unexec (const char *new_name, /* name of the new a.out file to be created * | |||
| 268 | it is still executing. If problems occur, everything is still | 282 | it is still executing. If problems occur, everything is still |
| 269 | intact. NOT implemented. */ | 283 | intact. NOT implemented. */ |
| 270 | 284 | ||
| 271 | /* Open the input and output a.out files */ | 285 | /* Open the input and output a.out files. */ |
| 272 | old = emacs_open (old_name, O_RDONLY, 0); | 286 | old = emacs_open (old_name, O_RDONLY, 0); |
| 273 | if (old < 0) | 287 | if (old < 0) |
| 274 | { perror (old_name); exit (1); } | 288 | unexec_error (old_name); |
| 275 | new = emacs_open (new_name, O_CREAT | O_RDWR | O_TRUNC, 0777); | 289 | new = emacs_open (new_name, O_CREAT | O_RDWR | O_TRUNC, 0777); |
| 276 | if (new < 0) | 290 | if (new < 0) |
| 277 | { perror (new_name); exit (1); } | 291 | unexec_error (new_name); |
| 278 | 292 | ||
| 279 | /* Read the old headers */ | 293 | /* Read the old headers. */ |
| 280 | read_header (old, &hdr, &auxhdr); | 294 | read_header (old, &hdr, &auxhdr); |
| 281 | 295 | ||
| 282 | brk_on_dump = (long) sbrk (0); | 296 | brk_on_dump = (long) sbrk (0); |
| 283 | 297 | ||
| 284 | /* Decide how large the new and old data areas are */ | 298 | /* Decide how large the new and old data areas are. */ |
| 285 | old_size = auxhdr.exec_dsize; | 299 | old_size = auxhdr.exec_dsize; |
| 286 | /* I suspect these two statements are separate | 300 | /* I suspect these two statements are separate |
| 287 | to avoid a compiler bug in hpux version 8. */ | 301 | to avoid a compiler bug in hpux version 8. */ |
| 288 | i = (long) sbrk (0); | 302 | i = (long) sbrk (0); |
| 289 | new_size = i - auxhdr.exec_dmem; | 303 | new_size = i - auxhdr.exec_dmem; |
| 290 | 304 | ||
| 291 | /* Copy the old file to the new, up to the data space */ | 305 | /* Copy the old file to the new, up to the data space. */ |
| 292 | lseek (old, 0, 0); | 306 | check_lseek (old, 0, 0); |
| 293 | copy_file (old, new, auxhdr.exec_dfile); | 307 | copy_file (old, new, auxhdr.exec_dfile); |
| 294 | 308 | ||
| 295 | /* Skip the old data segment and write a new one */ | 309 | /* Skip the old data segment and write a new one. */ |
| 296 | lseek (old, old_size, 1); | 310 | check_lseek (old, old_size, 1); |
| 297 | save_data_space (new, &hdr, &auxhdr, new_size); | 311 | save_data_space (new, &hdr, &auxhdr, new_size); |
| 298 | 312 | ||
| 299 | /* Copy the rest of the file */ | 313 | /* Copy the rest of the file. */ |
| 300 | copy_rest (old, new); | 314 | copy_rest (old, new); |
| 301 | 315 | ||
| 302 | /* Update file pointers since we probably changed size of data area */ | 316 | /* Update file pointers since we probably changed size of data area. */ |
| 303 | update_file_ptrs (new, &hdr, &auxhdr, auxhdr.exec_dfile, new_size-old_size); | 317 | update_file_ptrs (new, &hdr, &auxhdr, auxhdr.exec_dfile, new_size-old_size); |
| 304 | 318 | ||
| 305 | /* Save the modified header */ | 319 | /* Save the modified header. */ |
| 306 | write_header (new, &hdr, &auxhdr); | 320 | write_header (new, &hdr, &auxhdr); |
| 307 | 321 | ||
| 308 | /* Close the binary file */ | 322 | /* Close the binary file. */ |
| 309 | emacs_close (old); | 323 | emacs_close (old); |
| 310 | emacs_close (new); | 324 | emacs_close (new); |
| 311 | } | 325 | } |