100-PR23254-ld.bfd-mishandles-file-pointers-while-scanni.patch 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. From: Alan Modra <amodra@gmail.com>
  2. Date: Tue, 5 Jun 2018 21:04:00 +0930
  3. Subject: [PATCH] PR23254, ld.bfd mishandles file pointers while scanning
  4. archive
  5. Best practice is to not mix lseek/read with fseek/fread on the same
  6. underlying file descriptor, as not all stdio implementations will cope.
  7. Since the plugin uses lseek/read while bfd uses fseek/fread this patch
  8. reopens the file for exclusive use by the plugin rather than trying to
  9. restore the file descriptor. That allows the plugin to read the file
  10. after plugin_call_claim_file too.
  11. bfd/
  12. PR 23254
  13. * plugin.c (bfd_plugin_open_input): Allow for possibility of
  14. nested archives. Open file again for plugin.
  15. (try_claim): Don't save and restore file position. Close file
  16. if not claimed.
  17. * sysdep.h (O_BINARY): Define.
  18. ld/
  19. PR 23254
  20. * plugin.c (plugin_call_claim_file): Revert 2016-07-19 patch.
  21. (plugin_object_p): Don't dup file descriptor.
  22. ---
  23. --- a/bfd/plugin.c
  24. +++ b/bfd/plugin.c
  25. @@ -165,14 +165,22 @@ bfd_plugin_open_input (bfd *ibfd, struct
  26. bfd *iobfd;
  27. iobfd = ibfd;
  28. - if (ibfd->my_archive && !bfd_is_thin_archive (ibfd->my_archive))
  29. - iobfd = ibfd->my_archive;
  30. + while (iobfd->my_archive
  31. + && !bfd_is_thin_archive (iobfd->my_archive))
  32. + iobfd = iobfd->my_archive;
  33. file->name = iobfd->filename;
  34. if (!iobfd->iostream && !bfd_open_file (iobfd))
  35. return 0;
  36. - file->fd = fileno ((FILE *) iobfd->iostream);
  37. + /* The plugin API expects that the file descriptor won't be closed
  38. + and reused as done by the bfd file cache. So open it again.
  39. + dup isn't good enough. plugin IO uses lseek/read while BFD uses
  40. + fseek/fread. It isn't wise to mix the unistd and stdio calls on
  41. + the same underlying file descriptor. */
  42. + file->fd = open (file->name, O_RDONLY | O_BINARY);
  43. + if (file->fd < 0)
  44. + return 0;
  45. if (iobfd == ibfd)
  46. {
  47. @@ -196,12 +204,12 @@ try_claim (bfd *abfd)
  48. int claimed = 0;
  49. struct ld_plugin_input_file file;
  50. + file.handle = abfd;
  51. if (!bfd_plugin_open_input (abfd, &file))
  52. return 0;
  53. - file.handle = abfd;
  54. - off_t cur_offset = lseek (file.fd, 0, SEEK_CUR);
  55. claim_file (&file, &claimed);
  56. - lseek (file.fd, cur_offset, SEEK_SET);
  57. + if (!claimed)
  58. + close (file.fd);
  59. return claimed;
  60. }
  61. --- a/bfd/sysdep.h
  62. +++ b/bfd/sysdep.h
  63. @@ -108,6 +108,10 @@ extern char *strrchr ();
  64. #ifndef O_ACCMODE
  65. #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
  66. #endif
  67. +/* Systems that don't already define this, don't need it. */
  68. +#ifndef O_BINARY
  69. +#define O_BINARY 0
  70. +#endif
  71. #ifndef SEEK_SET
  72. #define SEEK_SET 0
  73. --- a/ld/plugin.c
  74. +++ b/ld/plugin.c
  75. @@ -1053,14 +1053,10 @@ plugin_call_claim_file (const struct ld_
  76. {
  77. if (curplug->claim_file_handler)
  78. {
  79. - off_t cur_offset;
  80. enum ld_plugin_status rv;
  81. called_plugin = curplug;
  82. - cur_offset = lseek (file->fd, 0, SEEK_CUR);
  83. rv = (*curplug->claim_file_handler) (file, claimed);
  84. - if (!*claimed)
  85. - lseek (file->fd, cur_offset, SEEK_SET);
  86. called_plugin = NULL;
  87. if (rv != LDPS_OK)
  88. set_plugin_error (curplug->name);
  89. @@ -1126,12 +1122,6 @@ plugin_object_p (bfd *ibfd)
  90. }
  91. file.handle = input;
  92. - /* The plugin API expects that the file descriptor won't be closed
  93. - and reused as done by the bfd file cache. So dup one. */
  94. - file.fd = dup (file.fd);
  95. - if (file.fd < 0)
  96. - return NULL;
  97. -
  98. input->abfd = abfd;
  99. input->view_buffer.addr = NULL;
  100. input->view_buffer.filesize = 0;