Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RuntimeException in MessageSchema on Android with Proguard #6463

Closed
MatFl opened this issue Aug 1, 2019 · 18 comments
Closed

RuntimeException in MessageSchema on Android with Proguard #6463

MatFl opened this issue Aug 1, 2019 · 18 comments

Comments

@MatFl
Copy link

MatFl commented Aug 1, 2019

Version: v3.9.0
Language: Java/Android
Protoc gradle plugin 0.8.10 for java with option "lite"

When running an proguard obfuscated android app a Runtime Exception is thrown when trying to build a Proto with it's Builder.

java.lang.RuntimeException: Field fieldName_ for xxx.yyy.z.b$d not found. Known fields are [private java.lang.String xxx.yyy.z.b$d.h, ...]
        at com.google.e.ck.a(MessageSchema.java:608)
        at com.google.e.ck.a(MessageSchema.java:502)
        at com.google.e.ck.a(MessageSchema.java:221)
        at com.google.e.bz.a(ManifestSchemaFactory.java:85)
        at com.google.e.bz.a(ManifestSchemaFactory.java:71)
        at com.google.e.dc.a(Protobuf.java:93)
        at com.google.e.dc.c(Protobuf.java:107)
        at com.google.e.bh.M(GeneratedMessageLite.java:170)
        at com.google.e.bh$a.ab(GeneratedMessageLite.java:386)
        at com.google.e.bh$a.ac(GeneratedMessageLite.java:394)
        at xxx.yyy.a(XXX)

It seems than since 3.8.0 the new Javalite runtime uses reflection for the Schemas. I thought the lite should NOT be using any reflection at all.

@m0hamed
Copy link
Contributor

m0hamed commented Aug 28, 2019

Any updates on this? Is this a bug? going forward is javalite runtime always going to use reflection and not work with proguard/r8?

@grill2010
Copy link

grill2010 commented Oct 6, 2019

Is there any workaround for this?
I use proguard in my project and I get the same error message. I know this happens because of accessing fields via reflection with hardcoded variable names but shouldn't it possible to tell proguard to just ignore these generated classes? I've already tried many things now in the proguatd-rules files but I'm not able to get it work. Maybe anyone could point me in the right direction?


Edit: adding the following line to your proguard-rules file helps to get rid of the error but keep in mind that your protobuf messages will then not be processed by proguard at all.

-keep class * extends com.google.protobuf.GeneratedMessageLite { *; }

@rafi-kamal
Copy link
Contributor

rafi-kamal commented Nov 13, 2019

I've added a proguard config here as a workaround. Please let me know if it doesn't solve the problem.

@MatFl
Copy link
Author

MatFl commented Nov 13, 2019

Using a proguard exception is a workaround AT MOST, but definitely not a solution! I still think reflection should not be used in lite variant at all.

@rafi-kamal
Copy link
Contributor

I think this was needed to remove unused fields from a message. @donaldchai could you please add more context?

@donaldchai
Copy link
Contributor

MessageSchema is used to avoid generating hashCode/equals/(de)serialization methods since a small schema would be more compact. Reflection is used to initialize the internal schema data structures the first time.

Removal of unused fields is not directly related.

I filed https://issuetracker.google.com/issues/144631039 for R8 to support obfuscation.

@jombie
Copy link

jombie commented Dec 1, 2019

I am not able to get around this when using above proguard rule:
-keepclassmembers class * extends com.google.protobuf.GeneratedMessageLite { <fields>; }
Fails with message "Field [fieldName] for [messageClass.getName(]) not found. Known fields are list of [fields]"

Is there any alternative or any other configuration that I should try.

@juanpmarin
Copy link

@jombie I'm running with the same problem, did you find out a solution?

@thaidn
Copy link

thaidn commented May 22, 2020

I am not able to get around this when using above proguard rule:
-keepclassmembers class * extends com.google.protobuf.GeneratedMessageLite { <fields>; }
Fails with message "Field [fieldName] for [messageClass.getName(]) not found. Known fields are list of [fields]"

Is there any alternative or any other configuration that I should try.

The following config works for me:

-keep class * extends com.google.protobuf.GeneratedMessageLite { *; }

thaidn added a commit to thaidn/androidx-security-issue that referenced this issue May 22, 2020
AndroidX Security delegates crypto operation to Tink which
depends on Protobuf Javalite. Recently Protobuf Javalite
introduced a change that relies on reflection, which doesn't
work with Proguard.

This change adds a rule that keeps the (shaded) Protobuf
classes in Tink as-is.

See also:
 - https://buganizer.corp.google.com/issues/154315507
 - tink-crypto/tink#361
 - protocolbuffers/protobuf#6463
 - https://b.corp.google.com/issues/144631039
@ubarua123
Copy link

ubarua123 commented Jan 12, 2021

The proguard rule worked for me but increased my app size by 3 MBs 😞

@kyze8439690
Copy link

kyze8439690 commented Jan 21, 2021

I am not able to get around this when using above proguard rule:
-keepclassmembers class * extends com.google.protobuf.GeneratedMessageLite { <fields>; }
Fails with message "Field [fieldName] for [messageClass.getName(]) not found. Known fields are list of [fields]"
Is there any alternative or any other configuration that I should try.

The following config works for me:

-keep class * extends com.google.protobuf.GeneratedMessageLite { *; }

This proguard rule raise a new exception:

java.lang.ArrayIndexOutOfBoundsException: length=11; index=11

downgrade com.google.protobuf:protobuf-javalite from 3.13.0 to 3.11.4 solve this issue

@tucson-tom
Copy link

Ack. What a lame bug. ProGuard is generally enabled on release builds but not debug builds by default in Android Studio, so the result is APK/App Bundles that use protobuf crash immediately on startup but debug versions are totally fine. Also, why is this issue closed? Seems like a critical bug.

@Dimezis
Copy link

Dimezis commented Jun 25, 2021

@tucson-tom it's not a bug, and it's not critical. Proto Messages use reflection in some cases, which Proguard can't know about unless you describe it in its rules.
So naturally it strips off those fields, methods and classes that it thinks are not used (but in fact are used via reflection).

Just add a Proguard rule and that's it, that's basically why those rules exist

@FZambia
Copy link

FZambia commented Jul 16, 2021

This issue caused lots of problems in my library, I am not a Java developer personally and could not reproduce issue for a long time. Now looking at the reason it seems to me that things are broken in Protobuf Java ecosystem. There should be at least a way for library developers to avoid asking library users to add proguard rules manually into their project. Maybe this way already exists?

@skjolber
Copy link

skjolber commented Jul 1, 2022

I'm having problems as well, as I'd like to keep the code obfuscated. It is possible to turn of the use of reflection?

@ntoskrnl
Copy link

This issue caused lots of problems in my library, I am not a Java developer personally and could not reproduce issue for a long time. Now looking at the reason it seems to me that things are broken in Protobuf Java ecosystem. There should be at least a way for library developers to avoid asking library users to add proguard rules manually into their project. Maybe this way already exists?

There is a way: Library should include pro guard rules in META-INF/proguard in their jar. It has been used by other open source libraries for years already.

@skjolber
Copy link

Seems the generator we're using is outputting code which is not designed to be obfuscated, so unless you're up for writing your own generator, disabling obfuscation with proguard rules is the only alternative.

@nikiizvorski
Copy link

nikiizvorski commented Aug 29, 2022

We are having the same issue. The only solution we currently have is using the following rule in ProGuard which seems to work as expected. I believe this should be handled on the protobuf library. Here is the rules that work:

-keep class * extends com.google.protobuf.GeneratedMessageLite { *; }

And here is the rule that generates the problem mentioned here:

-keep,allowobfuscation class * extends com.google.protobuf.GeneratedMessageLite { *; }

Another solution would be to keep the members of the classes but let them obfuscated like so:

-keepclassmembers class * extends com.google.protobuf.GeneratedMessageLite { *; }

and then adding a -dontnote toyourpackagewhereprotobufclassesare as long as they aren't a public class for the descriptors

Let us know if there would be a version that we could use. This only happens after we migrated from Lite version to the new javalite versions. I pretty much tested all without the RC versions so far.

aarongable pushed a commit to chromium/chromium that referenced this issue Dec 6, 2022
Re: https://crrev.com/c/4063747 and
protocolbuffers/protobuf#6463

Bug: 1395764
Change-Id: Id598afb69167d85de27e14281f368649a30564d0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4067023
Commit-Queue: Stefano Duo <[email protected]>
Reviewed-by: Tommy Nyquist <[email protected]>
Auto-Submit: Stefano Duo <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1079833}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests