Clockwork

hibernate3-maven-plugin fails with Java 1.7

If you're using Maven's hibernate3-maven-plugin for creating a DDL file from your entities, you might encounter the following error when using Java 1.7:

Execution default of goal org.codehaus.mojo:hibernate3-maven-plugin:2.2:hbm2ddl failed:
An AnnotationConfiguration instance is required

The reason seems to be a broken JRE detection in the Mojo code, which mistakenly assumes that Java 1.7 does not support annotations. However, I haven't checked that in depth.

The fix is pretty easy. In the plugin configuration of the hibernate3-maven-plugin, add an implementation property to the componentProperties like this:

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>hibernate3-maven-plugin</artifactId>
  <version>2.2</version>
  <configuration>
    <componentProperties>
      <implementation>annotationconfiguration</implementation>
    </componentProperties>
  </configuration>
</plugin>

This enforces the use of an AnnotationConfiguration instance.

Arduino auf Fedora 15 einrichten

Die Arduino-Plattform ist eine offene Entwicklungsplattform für kleine Hardwareprojekte, inklusive einer Entwicklungsumgebung und verschiedener günstiger Boards wie dem Arduino Uno. Wegen verschiedener Bugs ist die Installation der Entwicklungsumgebung auf einem System mit Fedora 15 leider nicht ganz trivial.

Die notwendigen Pakete befinden sich im Fedora-Repository. Zuerst installieren wir also die Arduino-IDE und stellen die Gruppenrechte her, die zum Zugriff auf die USB-Schnittstelle benötigt werden:

sudo yum install 'arduino*'
sudo usermod -a -G uucp,dialout,lock $USER

Neben der IDE werden der C-Compiler avr-gcc in Version 4.6.1-2 und die avr-libc in Version 1.7.0 installiert. Diese Version des Compilers wirft allerdings nur Fehlermeldungen. Ein Update steht schon bereit, liegt derzeit aber noch in fedora-testing und muss deshalb explizit installiert werden:

sudo yum --enablerepo=updates-testing update 'avr-*'

Danach ist der avr-gcc in Version 4.6.1-3 und die avr-libc in Version 1.7.1 installiert. Die IDE kann nun gestartet und die Sketches können kompiliert werden.

Allerdings bleibt noch ein Problem: durch eine zu aggressive Compiler-Optimierung funktioniert die delay()-Funktion unter Umständen nicht. So leuchtet bei dem Beispiel Blink die Test-LED dauerhaft, statt zu blinken. Die Ursache dafür lässt sich zum Beispiel durch einen Eingriff in eine Datei beheben. Folgender Patch führt diese Änderung aus:

sudo patch -d /usr/share/arduino/hardware/arduino/cores/arduino wiring.c << __END__
25a26
> #include <avr/delay.h>
106c107
< {
---
> {/*
114a116
> */ _delay_ms(ms);
__END__

Danach steht der Experimentierfreude nichts mehr im Wege!

Treppenlicht 2.0

Es ist schon fantastisch, was man mit modernen LEDs alles anstellen kann.

Diese Wendeltreppe zum Beispiel soll dezent und Strom sparend beleuchtet werden, damit man sie auch im Dunkeln sicher benutzen kann. Eine Weihnachtslichterkette erfüllte den Zweck bisher. Allerdings war sie recht schwach und gab der Treppe außerdem einen hässlichen Partykeller-Look.

Dieser Blogartikel beschreibt, wie man sich mit ein wenig handwerklichem Geschick und geringem Aufwand eine Treppenbeleuchtung selbst bauen kann.

Read this article...
Setting a renderer on JComboBox

When setting a custom renderer to a JComboBox, the usual way is to extend a DefaultListCellRenderer and override the getListCellRendererComponent() method. However, this may lead to ugly comboboxes on some Look and Feels. As you can see on the top combobox, it is rendered considerably smaller and with the letters sticked to the left border, just by using a DefaultListCellRenderer. The Look and Feel seems to use a special renderer class for proper rendering, as it is shown in the combobox below.

A solution is to use a proxy ListCellRenderer instead, which only converts the value and then delegates the rendering to the original renderer. For example:

public class ListCellRendererProxy implements ListCellRenderer {
  private final ListCellRenderer delegate;

  public ListCellRendererProxy(ListCellRenderer delegate) {
    this.delegate = delegate;
  }
  
  @Override
  public Component getListCellRendererComponent(JList list, Object value,
                int index, boolean isSelected, boolean cellHasFocus) {
    // modify the value here...
    return delegate.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
  }
}

The renderer proxy can be used like this:

JComboBox cbx = new JComboBox();
ListCellRenderer oldRenderer = cbx.getRenderer();
cbx.setRenderer(new ListCellRendererProxy(oldRenderer));

The combobox items are now converted to a string by a custom cell renderer, but are still rendered by the original renderer implementation of the current Look and Feel. However, while a single DefaultListCellRenderer instance can be shared with many JComboBox, a new renderer proxy needs to be instanciated per combobox.

PHP 5.3.7, eine Analyse

Das PHP-Entwicklerteam veröffentlichte vor wenigen Tagen die Version 5.3.7, nur um schon wenige Tage später vor deren Verwendung zu warnen [Link auf Heise-Artikel wurde nachträglich wieder entfernt]. Der Grund dafür war ein Fehler in der Funktion crypt(), welche bei bestimmten Hash-Verfahren lediglich das Salt zurückliefert. Das kann dazu führen, dass nach einem Update auf PHP 5.3.7 keine Benutzer sich mehr auf einem Webauftritt einloggen können oder sich bei einer Passwortänderung nach einem Update auf eine spätere PHP-Version nicht mehr einloggen können. In PHP 5.3.8 wurde der Fehler wieder behoben.

Dieser Artikel ist der Versuch einer Analyse, wie es zu dem Fehler kam und warum er erst nach der Release bemerkt wurde.

Die PHP-Funktion crypt() ist in der Datei php_crypt_r.c implementiert. Folgender Codeausschnitt baut dort den Passwort-Hash zusammen:

memcpy(passwd, MD5_MAGIC, MD5_MAGIC_LEN);
strlcpy(passwd + MD5_MAGIC_LEN, sp, sl + 1);
strcat(passwd, "$");

strcat() fügt eine Zeichenkette an das Ende eines Puffers. Die Funktion gilt als unsicher, da sie nicht prüft, ob der Zielpuffer genügend Speicherplatz zur Verfügung stellt. Wird die Zeichenkette zu lang, wird der nachfolgende Speicherbereich beschädigt – ein typisches Problem bei C-Sprachen.

Aus dem Grund wurde der Aufruf durch eine sicherere Funktion ersetzt. Leider ist aber gut gemeint das Gegenteil von gut gemacht.

memcpy(passwd, MD5_MAGIC, MD5_MAGIC_LEN);
strlcpy(passwd + MD5_MAGIC_LEN, sp, sl + 1);
strlcat(passwd, "$", 1);

strlcat() stellt sicher, dass der Puffer nicht über sein Ende hinaus beschrieben wird. Dazu wird dessen Größe übergeben. Und genau hier lag das Problem, denn statt der Größe von passwd wurde anscheinend die Größe des zu kopierenden Textes übergeben, nämlich 1. Da passwd zu dem Zeitpunkt bereits deutlich mehr als ein Zeichen enthält, tut strlcat() genau das, was es tun soll, nämlich gar nichts. Das “$”-Zeichen wird nicht angehängt, das tatsächliche Ergebnis weicht damit von dem gewünschten Ergebnis ab.

Solch ein Fehler ist eigentlich ein Lehrbuchbeispiel für Unit-Tests, und der Kommentar zum Bugfix (Revision 315218) deutet auch an, dass ein solcher existiert:

Unbreak crypt() (fix bug #55439)
# If you want to remove static analyser messages, be my guest,
# but please run unit tests after

Tatsächlich gibt es einen Test, der die crypt()-Funktion mit bestimmten Werten aufruft und das Ergebnis mit einem erwarteten Ergebnis vergleicht. Dieser Test schlägt Alarm, wenn er ausgeführt wird.

Dass PHP 5.3.7 dennoch veröffentlicht wurde, lässt eigentlich nur einen Schluss zu: Der Unit-Test wurde nicht ausgeführt oder der Alarm wurde schlichtweg ignoriert. Spätestens beim Bau der finalen Version unmitelbar vor der Veröffentlichung hätte dies aber stattfinden müssen. Alles andere wäre grob fahrlässig.

Zusammengefasst hatte der Fehler also folgende Ursachen:

  • die für C-Sprachen üblichen Probleme bei der sicheren Verarbeitung von Zeichenketten
  • eine missverständliche oder nicht verstandene Dokumentation der Funktion strlcat()
  • keine verbindlich vorgeschriebene fehlerfreie Ausführung der Unit-Tests vor der Freigabe einer Release

Insbesondere der letzte Punkt wiegt schwer und wirft ein schlechtes Licht auf die verantwortlichen PHP-Entwickler.