From eeba82a4d41c2994eede5815abeb7ea78ac525e4 Mon Sep 17 00:00:00 2001 From: Vasily E Date: Thu, 31 Jan 2019 17:17:14 +0300 Subject: [PATCH] Fixup error on empty .debug_pubtypes section (#215) * tox: explicitly set locale Locale affects GNU binutils output translation which cause run_readelf_tests.py to fail if system language is not English. Signed-off-by: Efimov Vasily * test: unittest reproducing error with empty ".debug_pubtypes" section Signed-off-by: Efimov Vasily * NameLUT: use `construct.If` to declare "name" field This patch also fixes problem with empty first entry. Signed-off-by: Efimov Vasily * NameLUT._get_entries: remove unused `bytes_read` Signed-off-by: Efimov Vasily --- elftools/dwarf/namelut.py | 31 ++++++++---------- test/test_pubtypes.py | 25 ++++++++++++++ .../empty_pubtypes/Makefile | 2 ++ .../empty_pubtypes/main | Bin 0 -> 9736 bytes .../empty_pubtypes/main.c | 1 + tox.ini | 2 ++ 6 files changed, 43 insertions(+), 18 deletions(-) create mode 100644 test/test_pubtypes.py create mode 100644 test/testfiles_for_unittests/empty_pubtypes/Makefile create mode 100755 test/testfiles_for_unittests/empty_pubtypes/main create mode 100644 test/testfiles_for_unittests/empty_pubtypes/main.c diff --git a/elftools/dwarf/namelut.py b/elftools/dwarf/namelut.py index b7de798..d24a5de 100755 --- a/elftools/dwarf/namelut.py +++ b/elftools/dwarf/namelut.py @@ -12,7 +12,7 @@ from collections import OrderedDict from ..common.utils import struct_parse from bisect import bisect_right import math -from ..construct import CString, Struct +from ..construct import CString, Struct, If NameLUTEntry = collections.namedtuple('NameLUTEntry', 'cu_ofs die_ofs') @@ -158,11 +158,14 @@ class NameLUT(collections.Mapping): entries = OrderedDict() cu_headers = [] offset = 0 + # According to 6.1.1. of DWARFv4, each set of names is terminated by + # an offset field containing zero (and no following string). Because + # of sequential parsing, every next entry may be that terminator. + # So, field "name" is conditional. entry_struct = Struct("Dwarf_offset_name_pair", self._structs.Dwarf_offset('die_ofs'), - CString('name')) - die_ofs_struct = self._structs.Dwarf_offset('die_ofs') - + If(lambda ctx: ctx['die_ofs'],CString('name'))) + # each run of this loop will fetch one CU worth of entries. while offset < self._size: @@ -174,29 +177,21 @@ class NameLUT(collections.Mapping): offset = (offset + namelut_hdr.unit_length + self._structs.initial_length_field_size()) - bytes_read = 0 # before inner loop, latch data that will be used in the inner # loop to avoid attribute access and other computation. hdr_cu_ofs = namelut_hdr.debug_info_offset - # read the first tuple for this CU. - entry = struct_parse(entry_struct, - self._stream) + # while die_ofs of the entry is non-zero (which indicates the end) ... while True: + entry = struct_parse(entry_struct, self._stream) + + # if it is zero, then we done. + if entry.die_ofs == 0: + break # add this entry to the look-up dictionary. entries[entry.name.decode('utf-8')] = NameLUTEntry( cu_ofs = hdr_cu_ofs, die_ofs = hdr_cu_ofs + entry.die_ofs) - # get the DIE offset entry alone. - die_ofs = struct_parse(die_ofs_struct, self._stream) - # if it is zero, then we done. - if die_ofs == 0: - break - else: - # else this is a valid DIE, get the name as well and - # construct the entry - entry.name = struct_parse(CString('name'), self._stream) - entry.die_ofs = die_ofs # return the entries parsed so far. return (entries, cu_headers) diff --git a/test/test_pubtypes.py b/test/test_pubtypes.py new file mode 100644 index 0000000..a0eb642 --- /dev/null +++ b/test/test_pubtypes.py @@ -0,0 +1,25 @@ +#------------------------------------------------------------------------------- +# elftools tests +# +# Efimov Vasiliy (real@ispras.ru) +# This code is in the public domain +#------------------------------------------------------------------------------- +import os +import unittest + +from elftools.elf.elffile import ELFFile + + +class TestEmptyPubtypes(unittest.TestCase): + def test_empty_pubtypes(self): + test_dir = os.path.join('test', 'testfiles_for_unittests') + with open(os.path.join(test_dir, 'empty_pubtypes', 'main'), 'rb') as f: + elf = ELFFile(f) + + # This test targets `ELFParseError` caused by buggy handling + # of ".debug_pubtypes" section which only has zero terminator + # entry. + self.assertEqual(len(elf.get_dwarf_info().get_pubtypes()), 0) + +if __name__ == '__main__': + unittest.main() diff --git a/test/testfiles_for_unittests/empty_pubtypes/Makefile b/test/testfiles_for_unittests/empty_pubtypes/Makefile new file mode 100644 index 0000000..20decd4 --- /dev/null +++ b/test/testfiles_for_unittests/empty_pubtypes/Makefile @@ -0,0 +1,2 @@ +main: +main: CFLAGS=-gpubnames -g -O0 diff --git a/test/testfiles_for_unittests/empty_pubtypes/main b/test/testfiles_for_unittests/empty_pubtypes/main new file mode 100755 index 0000000000000000000000000000000000000000..fc6c9b346e10e3a2e3719cb4abb3639097c20ff2 GIT binary patch literal 9736 zcmeHNYit}>6~40*J5HUf*GWp9q-};Ysock|?clghtCCqil6B-f>THS-b;s-7vAuL3 zW_LEVOGS&)Ms;b5B|r@be({hh@xw?3B7V?@R0)qiZlyw{^1~ns=?hY|gh;4azH{fE z_3U`Js*n(We59H4xaT|f-ZOXZ+2gi)+^Qt zQ`{w#+>^{eWNR`;>80dG}29CVnE)P zIr$PDebY&ioKl@kHJD_E?(%M_3BjCk_W`H6t~@@Tg;eo~s;^#NF01}ASE}g9q{n-@ zJ2I(oCY>wIglBqt!ad!QVm`84_M769?}5X|Wlfw%0~)n?GcFnfRPLM~E&le-9XA!e z^V7@=*Ns2j{p#~q2+J45PfX45+*rf=CfJM`c7c8*so6ckvPiayPNLvg*+e=A%Vaj6 zQx;1c7#`~Dw{}N%NA@6+`(QP+lG@4nENxA%qp~|yT~}Miq(sj~4F##UgO9)r7~#O4(Jo} zuD1|f?+wkp@?dQ4&#{w#xqLJ}bn&I57)h~<=a$wGyZC#sOFswh!-iXDz7nmOqqS@oqvzfFAHVn8&4v)A*5d$P%AsMS7aC5%qkKsRbeQ@+8~1AjX?D5~u*#7>lx|F1tPmksg_hV}>B4z@Hu z-1NBExAmUeKeKZOnaO7W*9F9-F)5Zrtjbd03n;g#ye}B~dY~`Z_N+b_ zG)}MS3${Pg5DRvmYK#SYPp&-_Gz-DrXs|OHZ0`#i@PmI}uu1mo$AG_%INtYxLax$k z239k$nt{~}tY%;}1OJ~4EMPrIG_SZ+aN{*9^YyA=UN@z*LFsX|PuZe$-d}A~I;|y$ zwz^ETVL3-c>klF>|L3)Gp7b*Tli2c}Pu15btyr%HOetNb^j^hjA3)URGI71)%xLc+ z3CmR?UW>3luczc%2<10OFCk`B{cImoI=7qg*aS#o9m^frA5-~bnJ0Bk`CV3euPRsO z|2gA*tiPfQb=q;DzyEHd{rGq(=ah^+k?u%mxThqwuCH|UL^``8U0t`i1;*~quAa`G z&b@LoegEjCveq@8TcIvG|gY6 zeOG9$+OFWHW<9tq*s5(@8@l0zK8)BvMC{w52k&marlMjWb3wg&*I{8Al=oIp~Nv^wNDxbAG3U(sX@o>KIP{)_- zY^ft>6mr+y{wMEPK?!zb6sT~sP=CbJReru*NcUkaW;s>n)YDj{H;1pi{SaS z+8z>P4W`#5WnHvZ&W*fQGRk@BzJFL$~W;!fBN4(j34(!O$>$6ybM zEtTiOkXvEjC|1q`N2Hy-mU&La@xMo3hTT|pt4L47-Wu2<+I{cWb7V)0c%E^;!9x59 zcIq!3ClblCA@Emmg)pvqeQ_N2*G+f`!Dm=MgPr_&9Lhr6ex>~R%eqz-T!h_VCl7xE zc51&r&fn_zFTlQ0)R?!E1*hngCMNK4x2%KxBi8WHvAAW4lwGhV(?!QFSWebTX7V|F z9W5)Bwru#gc5ju!iD?tmVAK5A{=4 z;)(H$Ei5~ga1snzK3g|U?`b;n2QT-a9llkk?kFqft*JyVMd5~yz$=x`S*4zEB-~I!W+(e$`#Q1o@KEWD(BC=UV4q2=$ zEe=E{=53e%5O)l}elYd|2{iQ0FzAO{J1sBaNjOXJJul;VU3^vYW`}Nm=ZSmlF-Q7k(L4JR~{wMfQ{kcZ~eT_yGoq`vA?S=>umoA3cUEreo$3l zFi>&EF~91=^Lp1%cy1?$VI1q%Adrpw&+Erd1@!x?bTC}#Fp#aYVsQn=(;1SN7|)!3 z^JUrVXRG@Cas9sA>fpbn@cx~#AAd(3{DQ(C@HPsvAAeUJ{J#{Q4)MI?#}C%Q?`(BZ zd%a-De*Aq3@6Xey!Y|grbDRh2)E`z863