Skip to content

Commit

Permalink
Fix jruby encoding in new thread (#12919)
Browse files Browse the repository at this point in the history
In jruby `runtime.evalScriptlet('Encoding::UTF_8')` can be broken under a newly created thread, which can cause protobuf encoding to fail. For example: https://github.com/ntkme/sass-embedded-host-ruby/actions/runs/5108602231/jobs/9182569583#step:5:544

It real issue seems to be in jruby itself. A bug report with minimal reproduction has been filed at jruby/jruby#7820

This PR fixes the problem by effectively replacing `runtime.evalScriptlet('Encoding::UTF_8')` with `runtime.getEncodingService().convertEncodingToRubyEncoding(org.jcodings.specific.UTF8Encoding.INSTANCE)`, which works on all threads.

Closes #12919

COPYBARA_INTEGRATE_REVIEW=#12919 from ntkme:fix-jruby-encoding 345680e
FUTURE_COPYBARA_INTEGRATE_REVIEW=#12919 from ntkme:fix-jruby-encoding 345680e
PiperOrigin-RevId: 536490901
  • Loading branch information
ntkme authored and copybara-github committed May 30, 2023
1 parent 472e8b4 commit 06544ba
Showing 1 changed file with 10 additions and 4 deletions.
14 changes: 10 additions & 4 deletions ruby/src/main/java/com/google/protobuf/jruby/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@
import com.google.protobuf.DescriptorProtos.FieldDescriptorProto;
import com.google.protobuf.Descriptors.FieldDescriptor;
import java.math.BigInteger;
import org.jcodings.Encoding;
import org.jcodings.specific.ASCIIEncoding;
import org.jcodings.specific.UTF8Encoding;
import org.jruby.*;
import org.jruby.exceptions.RaiseException;
import org.jruby.ext.bigdecimal.RubyBigDecimal;
Expand Down Expand Up @@ -141,12 +143,12 @@ public static IRubyObject checkType(
throw createInvalidTypeError(context, "boolean", fieldName, value);
break;
case BYTES:
value = validateAndEncodeString(context, "bytes", fieldName, value, "Encoding::ASCII_8BIT");
value = validateAndEncodeString(context, "bytes", fieldName, value, ASCIIEncoding.INSTANCE);
break;
case STRING:
value =
validateAndEncodeString(
context, "string", fieldName, symToString(value), "Encoding::UTF_8");
context, "string", fieldName, symToString(value), UTF8Encoding.INSTANCE);
break;
case MESSAGE:
if (value.getMetaClass() != typeClass) {
Expand Down Expand Up @@ -383,11 +385,15 @@ private static IRubyObject validateAndEncodeString(
String fieldType,
String fieldName,
IRubyObject value,
String encoding) {
Encoding encoding) {
if (!(value instanceof RubyString))
throw createInvalidTypeError(context, fieldType, fieldName, value);

value = ((RubyString) value).encode(context, context.runtime.evalScriptlet(encoding));
value =
((RubyString) value)
.encode(
context,
context.runtime.getEncodingService().convertEncodingToRubyEncoding(encoding));
value.setFrozen(true);
return value;
}
Expand Down

0 comments on commit 06544ba

Please sign in to comment.