@@ -708,8 +708,8 @@ Exec_stat MCDeployToELF(const MCDeployParameters& p_params, bool p_is_android)
708708 t_success = MCDeployThrow (kMCDeployErrorLinuxNoPayloadSection );
709709
710710 // Next check that there are no sections after the project section.
711- // (This check implies there are no segments after the project section
712- // since the section table is ordered by vaddr and segments can only
711+ // (This check implies there are no loadable segments after the project
712+ // section since the section table is ordered by vaddr and segments can only
713713 // contain stuff in sections).
714714 if (t_success)
715715 for (typename T::Shdr *t_section = t_project_section + 1 ; t_section < t_section_headers + t_header . e_shnum; t_section += 1 )
@@ -802,15 +802,17 @@ Exec_stat MCDeployToELF(const MCDeployParameters& p_params, bool p_is_android)
802802 else
803803 t_payload_delta = 0 ;
804804
805- // If the project section is not the last one, then work out the
806- // subsequent section data size/offset.
807- if (t_project_section - t_section_headers + 1 < t_header . e_shnum)
808- {
809- t_end_offset = (t_project_section + 1 ) -> sh_offset;
810- t_end_size = (t_section_headers[t_header . e_shnum - 1 ] . sh_offset + t_section_headers[t_header . e_shnum - 1 ] . sh_size) - t_end_offset;
811- }
812- else
813- t_end_offset = t_end_size = 0 ;
805+ // The sections of the file are not strictly ordered so the
806+ // remainder of the file requires examining the whole section table.
807+ t_end_offset = t_project_section->sh_offset + t_project_section->sh_size ;
808+
809+ t_end_size = 0 ;
810+ for (size_t i = 0 ; i < t_header.e_shnum ; i++)
811+ {
812+ uint32_t t_section_end = t_section_headers[i].sh_offset + t_section_headers[i].sh_size ;
813+ if (t_section_end > t_end_offset + t_end_size)
814+ t_end_size = t_section_end - t_end_offset;
815+ }
814816
815817 //
816818
@@ -821,16 +823,45 @@ Exec_stat MCDeployToELF(const MCDeployParameters& p_params, bool p_is_android)
821823 t_project_section -> sh_addr += t_payload_delta;
822824 t_project_section -> sh_size = t_project_size;
823825
824- t_project_segment -> p_filesz = t_payload_size + t_project_size ;
825- t_project_segment -> p_memsz = t_payload_size + t_project_size ;
826+ t_project_segment -> p_filesz += t_payload_delta + t_project_delta ;
827+ t_project_segment -> p_memsz += t_payload_delta + t_project_delta ;
826828
827- for (typename T::Shdr *t_section = t_project_section + 1 ; t_section < t_section_headers + t_header . e_shnum; t_section += 1 )
829+ // Update the sections that follow the project/payload
830+ for (typename T::Shdr* t_section = t_project_section + 1 ; t_section < t_section_headers + t_header . e_shnum; t_section += 1 )
831+ {
828832 if (t_section -> sh_offset >= t_end_offset)
829833 t_section -> sh_offset += t_project_delta + t_payload_delta;
834+ }
830835
831- t_header . e_shoff += t_project_delta + t_payload_delta;
832-
833- //
836+ // Adjust the section header table offset if it comes after the adjusted
837+ // sections.
838+ if (t_header.e_shoff >= t_end_offset)
839+ t_header.e_shoff += t_project_delta + t_payload_delta;
840+
841+ // Adjust the segment header table offset if it coems after the adjusted
842+ // sections.
843+ if (t_header.e_phoff >= t_end_offset)
844+ t_header.e_phoff += t_project_delta + t_payload_delta;
845+
846+ // Update the segments that follow the project/payload
847+ // Note that segments aren't necessarily in increasing order of file
848+ // offset.
849+ for (typename T::Phdr* t_segment = t_program_headers; t_segment < t_program_headers + t_header.e_phnum ; t_segment += 1 )
850+ {
851+ // Skip segments that precede the segment we adjusted
852+ if (t_segment == t_project_segment || t_segment->p_offset < t_end_offset)
853+ continue ;
854+
855+ // If any of these segments is a LOAD segment, we've broken the file!
856+ if (t_segment->p_type == PT_LOAD)
857+ {
858+ t_success = MCDeployThrow (kMCDeployErrorLinuxBadSectionOrder );
859+ break ;
860+ }
861+
862+ // Adjust the file offset for the segment contents
863+ t_segment->p_offset += t_payload_delta + t_project_delta;
864+ }
834865
835866 t_section_table_size = t_header . e_shnum * sizeof (typename T::Shdr);
836867 t_section_table_offset = t_header . e_shoff;
0 commit comments