[Firm] Probleme mit cparser

Moritz Kroll Moritz.Kroll at avira.com
Sun Feb 1 00:20:54 CET 2015


Hallo nochmal,

ich habe für Punkt 3. einen Patch im Anhang, der hoffentlich die
Bedingungen von C++03 7.1.3.2 erfüllt:

----
In a given non-class scope, a typedef specifier can be used to redefine
the name of any type declared in that scope to refer to the type to
which it already refers. [Example:
        typedef struct s { /* ... */ } s;
        typedef int I;
        typedef int I;
        typedef I I;
—
end example]
----

Der Patch löst bei den Windows-Headers auch die meisten Probleme mit
Compile-Zeit-Asserts.
Ein Problem bleibt aber:

4. Bei dem angehängten Testfall bekomme ich einen "variable length
array" Fehler. Das Hauptproblem scheint dieses zu sein: Wenn A ein
typedef einer Struktur ist, wird "(A *) 0" nicht als
EXPR_CLASS_INTEGER_CONSTANT aufgefasst, sondern nur als EXPR_CLASS_CONSTANT:

ast.c:is_constant_expression -> case EXPR_UNARY_CAST

if (is_type_scalar(type)) {
    expression_classification_t const cls
        = is_constant_expression(expression->unary.value);
    /* Can't be an integer constant anymore */
    return MIN(cls, EXPR_CLASS_CONSTANT);
}

Wenn ich hier einfach cls zurückgebe, funktioniert es. Ich schätze mal,
cls sollte aber nur unter speziellen Bedingungen direkt zurückgegeben
werden, oder? Sonst wäre der Spezialfall mit dem MIN ja wahrscheinlich
nicht eingebaut worden.

Schöne Grüße
Moritz


On 31.01.2015 01:33, Moritz Kroll wrote:
> Hallo zusammen,
>
> ich probiere nach einiger Zeit mal wieder cparser in einer aktuellen
> Version zu kompilieren, um aus Windows-Headers automatisch Informationen
> über API-Funktionen zu extrahieren (Namen, Parameternamen und -typen,
> Rückgabetyp, calling convention). Die Informationen verwende ich bei der
> Stack-Analyse von Funktionen in einem Disassembler. Ich verwende dazu
> ein eigenes "wrappergen"-Modul auf Basis von write_jna.
>
> Zuerst einmal bekomme ich bei eurer Anleitung
> (http://pp.ipd.kit.edu/firm/Download) diese Fehler:
>
> -------
> $ git clone http://pp.ipd.kit.edu/git/cparser.git
> Cloning into 'cparser'...
> remote: Counting objects: 14860, done.
> remote: Compressing objects: 100% (4436/4436), done.
> remote: Total 14860 (delta 10738), reused 14343 (delta 10343)
> Receiving objects: 100% (14860/14860), 2.83 MiB, done.
> Resolving deltas: 100% (10738/10738), done.
>
> $ cd cparser
> $ git submodule update --init
> Submodule 'libfirm' (http://pp.info.uni-karlsruhe.de/git/libfirm.git/)
> registere
> d for path 'libfirm'
> Cloning into 'libfirm'...
> fatal: The remote end hung up unexpectedly
> fatal: protocol error: bad pack header
> Clone of 'http://pp.info.uni-karlsruhe.de/git/libfirm.git/' into
> submodule path
> 'libfirm' failed
> -------
>
> Nachdem ich eine Weile daran verzweifelt war, hatte ich dann das Github
> Repository genommen.
>
> Dabei bin ich bei Git-Referenz c89dd8e auf ein paar Probleme gestoßen:
>
> 1. Die Option "--ms" hat keine Auswirkungen, da init_tokens aufgerufen
> wird, bevor das entsprechende "dialect" Flag in init_c_dialect gesetzt wird.
>
> 2. Bei der Deklaration von Funktionszeigertypen werden im MS-Modus keine
> calling convention modifier erlaubt (siehe
> https://msdn.microsoft.com/en-us/library/zxk0tw93.aspx und angehängter
> Testkäse (Hi Christoph ^_^) stdcall-func-typedef.c). Ich hab dazu einen
> Patch angehängt.
>
> 3. Im C++-Modus wird bei
>
> typedef long NTSTATUS;
> typedef NTSTATUS *PNTSTATUS;
> typedef long *PNTSTATUS;
>
> die zweite Definition von "PNTSTATUS" als unerlaubte Redefinition
> aufgefasst (siehe multi-typedef.cpp). An der entsprechenden Stelle in
> record_entity sollten aber eigentlich bereits alle typedefs übersprungen
> werden. Scheint ihm aber trotzdem nicht gleich genug zu sein. Vielleicht
> wegen den Zeigern?
>
> Wäre schön, wenn ihr meinen Patch einbauen könntet und ein paar aktive
> Blicke auf die beiden anderen Probleme werfen könntet ;)
>
> Schöne Grüße
> Moritz
>

--
Moritz Kroll
Software Developer & Researcher
Advanced Threat Research And Protection Systems
Email: moritz.kroll at avira.com

--
Avira Operations GmbH & Co. KG
Kaplaneiweg 1 | 88069 Tettnang | Deutschland / Germany
Telefon / Telephone: +49 7542-500 0
Telefax / Facsimile: +49 7542-500 3000

Registergericht: Amtsgericht Ulm, HRA 722586 | USt.-IdNr.: DE 815289569 | Pers. haftende Gesellschafterin: Avira OP GmbH | Firmensitz: Tettnang | Registergericht: Amtsgericht Ulm, HRB 726712 | Geschäftsführer: Travis Witteveen

Commercial Register: Amtsgericht Ulm, HRA 722586 | VAT-ID: DE 815289569 | Personally Liable Partner: Avira OP GmbH | Headquarters: Tettnang | Commercial Register: Amtsgericht Ulm, HRB 726712 | Chief Executive Officer (CEO): Travis Witteveen
-------------- next part --------------
>From bd0ff44e2873f3c47c324d9888f1799e4d7dc53c Mon Sep 17 00:00:00 2001
From: Moritz Kroll <moritz.kroll at avira.com>
Date: Sat, 31 Jan 2015 23:14:30 +0100
Subject: [PATCH] C++: Fix check whether type refers to type to which it
 already refers

---
 src/parser/parser.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/parser/parser.c b/src/parser/parser.c
index ed8e6f2..4eefd6d 100644
--- a/src/parser/parser.c
+++ b/src/parser/parser.c
@@ -3968,9 +3968,9 @@ entity_t *record_entity(entity_t *entity, const bool is_definition)
 				type_t *const type      = skip_typeref(entity->typedefe.type);
 				type_t *const prev_type = skip_typeref(previous->typedefe.type);
 				if (dialect.cpp) {
-					/* C++ allows double typedef if they are identical
+					/* C++ allows double typedef if they are identical (C++03 7.1.3.2)
 					 * (after skipping typedefs) */
-					if (type == prev_type)
+					if (types_compatible(type, prev_type))
 						goto finish;
 				} else {
 					/* GCC extension: redef in system headers is allowed */
-- 
1.8.0.msysgit.0

-------------- next part --------------
typedef struct {
    int field;
} A;

typedef char __C_ASSERT__[((long)&(((A *)0)->field) == 0) ? 1 : -1];


More information about the Firm mailing list