2
votes

Comment ce code peut-il utiliser des mots-clés réservés comme noms de champ?

J'ai trouvé la construction suivante dans l'ancien java bytecode en essayant de dépanner le démarrage de l'application serveur. Mon IDE a décompilé certaines bibliothèques tierces et je suis curieux de savoir comment cela peut être valide - jamais vu auparavant, les mots clés peuvent être utilisés comme noms de champs dans le bytecode.

La version de Bytecode est 48.0 (Java 1.4).

public final class f implements UserContext{

private final String try;
private final UserInfo do;

// a lot of code here 

public UserInfo getUserInfo(){
    return this.do;
}

public String getViewName(){
    return this.try;
}

}

On dirait que la bibliothèque a été compilée à l'aide de certaines fonctionnalités d'obfuscation, mais comment cela peut-il être au niveau JVM? Est-ce permis sans spécial drapeaux au démarrage de la JVM?

UPDATE : le nom de getter correct pour le champ UserInfo est getUserInfo - désolé de confondre tout le monde avec un nom ambigu pour les méthodes avec des valeurs de retour différentes, c'est un problème de copier-coller car le code est situé sur une machine distante sans accès direct au site.


4 commentaires

return this.do est identique à return do . Ce n'est pas un nom de champ, cela signifie simplement, retournez faire de vous-même. Lors de la programmation de java, l'ajouter est facultatif, le compilateur l'ajoutera, mais il peut rester lors de sa décompilation par la suite.


La vraie question devrait probablement être "Comment ce code peut-il utiliser des mots-clés réservés comme noms de champs?"


Ce que vous montrez n'est pas un bytecode. C'est du code Java décompilé. Autrement dit, le problème pourrait être dans le décompilateur, pas dans le code java lui-même.


@ M.Deinum à quel égard renvoie quelque chose «de vous-même» ne faisant pas référence à un champ par son nom?


4 Réponses :


0
votes

Vous ne pouvez pas utiliser de mots-clés comme noms de variable, voir chapitre 3.9 de la spécification du langage Java.

Le décompilateur vous a donné du code incorrect / bogué.


0 commentaires

5
votes

La spécification de la machine virtuelle Java (qui est chargée de définir à quoi ressemble le bytecode) place pas de contraintes liées aux mots-clés sur les noms des choses .

Ces contraintes n'existent que sur le niveau de langage Java . Le bytecode que vous avez utilisé ne se décompile pas en Java valide, car il utilise des noms qui ne sont pas valides dans le langage Java, mais qui sont valides pour la JVM.

Une logique similaire s'applique aux deux méthodes getViewName qui ne diffèrent que par le type de retour: Ceci est autorisé (et fonctionne parfaitement) en bytecode par la spécification JVM, mais la spécification du langage Java l'interdit.

La raison la plus courante d'un bytecode comme celui-ci est le code Java qui a été compilé en bytecode, puis obscurci .

Une autre raison possible est que le code n'a pas été produit à l'origine en compilant du code Java, mais un autre langage qui cible la JVM. C'est plutôt improbable dans ce cas, car personne ne nommerait une variable do alors qu'elle est censée contenir le nom de la vue.


2 commentaires

Merci, Joachim. C'est définitivement Java 1.4 et le code est écrit en ~ 2003-2004 (je ne sais pas si d'autres langages comme Groovy ou Scala étaient prêts pour la production à ce moment-là


… Et l'auteur de l'outil d'obscurcissement manquait de créativité pour trouver encore pire. Notez qu'au niveau du bytecode, même les champs peuvent avoir le même nom s'ils sont toujours reconnaissables par leur type. De plus, les noms ne sont même pas nécessaires pour former des mots, un saut de ligne serait également un nom valide et le nom du champ pourrait être a + 1 (ce qui est particulièrement amusant lorsque vous avez également une variable a et a + 2 , etc. Voir aussi cette réponse . façon, depuis Java 5, le compilateur peut générer des méthodes de pont qui ne diffèrent que dans les types de retour.



2
votes

Je penserais presque que le code était obscurci, mais vous le verriez également dans les noms de méthodes. Parfois, les obfuscateurs font des choses qui ne sont pas autorisées dans le langage, donc lorsque vous les décompilez, vous ne pouvez pas recompiler la source. Seule la syntaxe Java n'autorise pas do ou try en tant que noms de variables, la JVM (et les autres langages qui s'exécutent sur la JVM) ne s'en soucient pas.

Soit il s'agissait d'une obfuscation délibérée, soit ils n'étaient pas compilés à partir de classes Java.


3 commentaires

Il est assez courant de masquer uniquement les parties non publiques du code (par exemple, lorsqu'un autre code non masqué est nécessaire pour interagir avec le vôtre). Je suis presque sûr que c'est le résultat de l'obfuscation du bytecode.


@JoachimSauer, ça y ressemble. Bien sûr, les méthodes getViewName () sont également invalides, car elles ont la même signature.


Les gars, désolé: si bien sûr, c'était une erreur dans les noms de méthode - en raison du copier-coller. La seule question concerne les mots-clés.



1
votes

Cela pourrait être une forme d'obfuscation.

La chaîne try pourrait peut-être être trу . Ils sont en fait différents. Coupez-collez le premier et il sera traité comme le mot-clé réservé try . Coupez et collez le second et ce sera un nom de champ valide. Le y dans le second cas n'est pas un y normal. C'est un caractère Unicode différent.


1 commentaires

Merci, Roger, bon point. J'ai vérifié les octets - non, c'est dans ASCII ( \ 0x74 \ 0x72 \ 0x79 )