Bug 28320 - abidw - (non-deterministic) infinite loop in XML writer
Summary: abidw - (non-deterministic) infinite loop in XML writer
Status: UNCONFIRMED
Alias: None
Product: libabigail
Classification: Unclassified
Component: default (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Dodji Seketeli
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-09-09 09:30 UTC by gprocida
Modified: 2021-09-14 16:54 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
compressed library file (1.39 MB, application/gzip)
2021-09-09 09:30 UTC, gprocida
Details

Note You need to log in before you can comment on or make changes to this bug.
Description gprocida 2021-09-09 09:30:48 UTC
Created attachment 13659 [details]
compressed library file

libabigail version:

https://android.googlesource.com/platform/external/libabigail/+/4e975fe2bc039f3354fd7bb3df0ea9ed289fda40

This corresponds roughly to current master 190350a35f842574cf15b9a98f1ccbc3aa31a840. However, there are some minor differences. None currently in the XML writer or IR.

$ git diff --stat aosp/upstream-master HEAD include src tools
 include/abg-comparison.h  |    6 +
 include/abg-version.h     |    8 +
 src/abg-comparison-priv.h |    2 +
 src/abg-comparison.cc     |   16 ++
 src/abg-config.cc         |    9 +
 src/abg-leaf-reporter.cc  |   55 ++++-
 src/abg-reader.cc         |   54 ++--
 src/abg-reporter-priv.cc  |   88 ++-----
 src/abg-reporter-priv.h   |    2 +-
 src/abg-tools-utils.cc    |   11 +-
 tools/Makefile.am         |    8 +-
 tools/abidiff.cc          |    9 +-
 tools/abitidy.cc          | 1428 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 13 files changed, 1577 insertions(+), 119 deletions(-)

More significantly, abidw and its dependencies are compiled within a standardised Android build environment (Clang, compile flags, libc++ etc.).

With the attached file, libc.so, about 4% of

abidw libc.so --out-file /dev/null

invocations result in an infinite loop.

The line

    <class-decl name='DIR' is-struct='yes' visibility='default' is-declaration-only='yes' id='type-id-1114'/>

is emitted in a tight loop.
Comment 1 gprocida 2021-09-09 09:44:14 UTC
Stack trace from attaching GDB:

#0  __memcmp_avx2_movbe () at ../sysdeps/x86_64/multiarch/memcmp-avx2-movbe.S:66
#1  0x00005637c946e4a5 in std::__1::char_traits<char>::compare (__s1=0x5637ccb99550 "bionic/libc/upstream-freebsd/lib/libc/gen/glob.c", 
    __s2=0x5637ccb99550 "bionic/libc/upstream-freebsd/lib/libc/gen/glob.c", __n=48) at external/libcxx/include/__string:250
#2  std::__1::operator==<std::__1::allocator<char> > (__lhs=..., __rhs=...) at external/libcxx/include/string:3866
#3  0x00005637c9570157 in abigail::xml_writer::referenced_type_should_be_emitted (t=0x5637ccbb24b0, ctxt=..., tu=..., tu_is_last=false)
    at external/libabigail/src/abg-writer.cc:2267
#4  abigail::xml_writer::write_translation_unit (ctxt=..., tu=..., indent=<optimized out>, is_last=false)
    at external/libabigail/src/abg-writer.cc:2457
#5  0x00005637c9573700 in abigail::xml_writer::write_corpus (ctxt=..., corpus=..., indent=0, member_of_group=<optimized out>)
    at external/libabigail/src/abg-writer.cc:4508
#6  0x00005637c937bc7a in load_corpus_and_write_abixml (argv=0x7ffc078e0298, env=..., context=..., opts=...)
    at external/libabigail/tools/abidw.cc:654
#7  0x00005637c937a491 in main (argc=<optimized out>, argv=0x7ffc078e0298) at external/libabigail/tools/abidw.cc:893
Comment 2 gprocida 2021-09-09 12:30:57 UTC
Bisected to "Bug 27995 - Self comparison error from abixml file".
Comment 3 Dodji Seketeli 2021-09-13 10:23:21 UTC
Hello,

I couldn't reproduce this issue on the branch you mentioned, while compiling libabigail with gcc.

However, I tried punching in the dark a little bit.

Could you please try this patch and see if it as an impact at all?

diff --git a/src/abg-writer.cc b/src/abg-writer.cc
index 9f48dc92..46b6d456 100644
--- a/src/abg-writer.cc
+++ b/src/abg-writer.cc
@@ -2356,7 +2356,8 @@ write_translation_unit(write_context&		ctxt,
 	  // considered "opaque".
 	  if (class_decl_sptr class_type = is_class_type(t))
 	    if (class_type->get_is_declaration_only()
-		&& !ctxt.type_is_emitted(class_type))
+		&& !ctxt.type_is_emitted(class_type)
+		&& !ctxt.decl_only_type_is_emitted(class_type))
 	      write_type(class_type, ctxt,
 			 indent + c.get_xml_element_indent());
 	  continue;
Comment 4 Dodji Seketeli 2021-09-13 15:12:03 UTC
Hmmh, actually, this one might be the one to try, rather:

diff --git a/src/abg-writer.cc b/src/abg-writer.cc
index 9f48dc92..2062c326 100644
--- a/src/abg-writer.cc
+++ b/src/abg-writer.cc
@@ -2356,7 +2356,8 @@ write_translation_unit(write_context&		ctxt,
 	  // considered "opaque".
 	  if (class_decl_sptr class_type = is_class_type(t))
 	    if (class_type->get_is_declaration_only()
-		&& !ctxt.type_is_emitted(class_type))
+		&& !ctxt.type_is_emitted(class_type)
+		&& !ctxt.decl_only_type_is_emitted(class_type))
 	      write_type(class_type, ctxt,
 			 indent + c.get_xml_element_indent());
 	  continue;
@@ -2420,7 +2421,8 @@ write_translation_unit(write_context&		ctxt,
 	  // We handle types which have declarations *and* function
 	  // types here.
 	  type_base_sptr t(*i, noop_deleter());
-	  if (!ctxt.type_is_emitted(t))
+	  if (!ctxt.type_is_emitted(t)
+	      && !ctxt.decl_only_type_is_emitted(t))
 	    {
 	      if (decl_base* d = get_type_declaration(*i))
 		{
Comment 5 gprocida 2021-09-13 20:09:27 UTC
FTR, the patches in comments #3 and #4 did not help.

I have been able to reproduce *a* problem if not *the* problem using a vanilla GCC build. See https://sourceware.org/pipermail/libabigail/2021q3/003667.html.
Comment 6 gprocida 2021-09-14 16:54:46 UTC
I've debugged the issue I see with the test suite (with the debugging patches I posted active).

The triggering command is:

build/tools/abipkgdiff --verbose --self-check --d1 tests/data/test-diff-pkg/nmap-debuginfo-7.70-5.el8_testjcc.x86_64.rpm --d2 tests/data/test-diff-pkg/nmap-debuginfo-7.70-5.el8_testjcc.x86_64.rpm tests/data/test-diff-pkg/nmap-7.70-5.el8_testjcc.x86_64.rpm tests/data/test-diff-pkg/nmap-7.70-5.el8_testjcc.x86_64.rpm

It triggers on "struct lua_State". The type already in the map (already emitted) is declaration only with no named_definition_of_declaration while the other is a canonical type (get_naked_canonical_type gives the same pointer).

Tracing through what the deep_ptr_eq_functor does:

The first type is a class_decl, as is the second, and end we up in equals(class_decl, class_decl). One of them is declaration only, so this function delegates to equals(class_or_union, class_or_union). One of the types is declaration only, neither are anonymous and ODR is relevant, so equality checks the scoped names.

The scoped names are identical and equality evaluates to true.

On the other hand, the hash values are completely different.