From 5cc80727d68fbdaf4f9f809a43d53e35c183be80 Mon Sep 17 00:00:00 2001 From: r-zakarya <82443831+r-zakarya@users.noreply.github.com> Date: Fri, 28 Aug 2026 16:46:24 +0100 Subject: [PATCH] fix(android): l'exception etait lue apres sa liberation Register et Login mettaient leur gestionnaire d'erreur en file avec TThread.Queue, puis y lisaient E.ClassName et E.Message. Or la file s'execute sur le thread principal bien apres que le except a rendu la main, et Delphi libere E en sortant du gestionnaire : c'etait une lecture apres liberation. Elle rendait un message vide - "Login failed: EPMACrypto - " sans la raison - et parfois une violation d'acces qui remontait a FMX sans rien laisser au journal. Le vrai motif de l'echec n'a donc jamais ete affiche. On ne met plus en file que des chaines, qui survivent. Co-Authored-By: Claude Opus 5 --- mainApk.pas | 62 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 10 deletions(-) diff --git a/mainApk.pas b/mainApk.pas index ca9e079..2ff8e21 100644 --- a/mainApk.pas +++ b/mainApk.pas @@ -1935,13 +1935,24 @@ begin end); except on E: Exception do + begin + // LE TEXTE EST PRIS ICI, PAS DANS LA FILE. + // + // TThread.Queue s'execute sur le thread principal bien apres que le + // except a rendu la main - et Delphi libere l'objet E en sortant du + // gestionnaire. Lire E.Message depuis la file etait donc une lecture + // apres liberation : elle rendait un message vide, et parfois une + // violation d'acces qui remontait a FMX sans rien laisser au journal. + // On ne met en file que des chaines, qui, elles, survivent. + var LWhy := E.ClassName + ' - ' + E.Message; TThread.Queue(nil, procedure begin SetBusy(False); - Log('Register failed: ' + E.ClassName + ' - ' + E.Message); + Log('Register failed: ' + LWhy); StatusErr('Could not create the vault - see log'); end); + end; end; end).Start; end; @@ -1978,7 +1989,9 @@ begin begin try FVaultPwd := APwd; // avant l'ouverture : c'est lui qui la fait + Log('login: opening the local container'); LPlain := OpenContainer(LoadLocalContainer, APwd); + Log(Format('login: opened, %d chars', [Length(LPlain)])); LOwner := ''; LDoc := TJSONObject.ParseJSONValue(LPlain) as TJSONObject; if LDoc <> nil then @@ -1994,30 +2007,59 @@ begin TThread.Queue(nil, procedure begin Log('Vault belongs to ' + LOwner + ', not ' + AUser); end); + Log('login: writing the cache'); SaveVault(LPlain, FETag, APwd, BiometricAvailable, False, FPinSealed, FKey, FKeySalt, FKeyIters); + Log('login: cache written'); TThread.Queue(nil, procedure begin - SetBusy(False); - if LOwner <> '' then FUser := LOwner else FUser := AUser; - // Meme regle qu'a la creation : ce mot de passe ouvre le conteneur - // local et s'arrete la. - FVaultPwd := APwd; - - AdoptVault(LPlain); + // LE RETOUR SUR LE THREAD PRINCIPAL N'EST GARDE PAR RIEN, et c'est + // le seul endroit du chemin qui ne l'etait pas : ni le except du + // thread, ni celui du pont ne le couvrent - il s'execute bien apres + // que les deux ont rendu la main. Une faute ici remontait donc a + // FMX, qui montrait "Access violation" pendant que le journal + // s'arretait sans un mot. + try + Log('login: adopting'); + SetBusy(False); + if LOwner <> '' then FUser := LOwner else FUser := AUser; + // Meme regle qu'a la creation : ce mot de passe ouvre le + // conteneur local et s'arrete la. + FVaultPwd := APwd; + AdoptVault(LPlain); + Log('login: done'); + except + on E: Exception do + begin + SetBusy(False); + Log('login: adopt FAILED: ' + E.ClassName + ' - ' + E.Message); + StatusErr('Could not display the vault - see log'); + end; + end; end); except on E: Exception do + begin + // LE TEXTE EST PRIS ICI, PAS DANS LA FILE. + // + // TThread.Queue s'execute sur le thread principal bien apres que le + // except a rendu la main - et Delphi libere l'objet E en sortant du + // gestionnaire. Lire E.Message depuis la file etait donc une lecture + // apres liberation : elle rendait un message vide, et parfois une + // violation d'acces qui remontait a FMX sans rien laisser au journal. + // On ne met en file que des chaines, qui, elles, survivent. + var LWhy := E.ClassName + ' - ' + E.Message; TThread.Queue(nil, procedure begin SetBusy(False); - Log('Login failed: ' + E.ClassName + ' - ' + E.Message); + Log('Login failed: ' + LWhy); // GCM echoue a sa verification quand la cle est fausse, et son // message ne le dit pas. Le cas de loin le plus frequent. - Status('Wrong master password'); + StatusErr('Wrong master password'); end); + end; end; end).Start; end;