After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 763831 - g_enum_get_value on Soup.Message.tls_errors leads to crash
g_enum_get_value on Soup.Message.tls_errors leads to crash
Status: RESOLVED FIXED
Product: vala
Classification: Core
Component: Code Generator: GType
0.30.x
Other Mac OS
: Normal normal
: ---
Assigned To: Vala maintainers
Vala maintainers
Depends on:
Blocks:
 
 
Reported: 2016-03-17 18:23 UTC by Marcin Lewandowski
Modified: 2016-09-16 16:44 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Testcase (138 bytes, text/plain)
2016-03-19 09:05 UTC, Marcin Lewandowski
  Details
patch solving the issue (1.15 KB, patch)
2016-08-20 10:10 UTC, therebedragons111
none Details | Review
codegen: Distinguish between Enum and Flags for their to_string() (2.44 KB, patch)
2016-09-16 16:44 UTC, Rico Tzschichholz
committed Details | Review

Description Marcin Lewandowski 2016-03-17 18:23:06 UTC
The following piece of code

(where message is of type Soup.Message)

if(message.status_code == Soup.Status.SSL_FAILED) {
  warning(@"TLS problem $(message.tls_errors)");
}

ends up with crash on g_enum_get_value in the underlying code

g_object_get (_tmp105_, "tls-errors", &_tmp106_, NULL);
_tmp107_ = _tmp106_;
_tmp108_ = g_enum_get_value (g_type_class_ref (g_tls_certificate_flags_get_type ()), _tmp107_);
Comment 1 Ben 2016-03-18 19:35:16 UTC
Can you provide a self-contained test case that crashes?
Comment 2 Marcin Lewandowski 2016-03-19 09:05:17 UTC
Created attachment 324319 [details]
Testcase

Compile with valac --pkg libsoup-2.4 test.vala
Comment 3 Al Thomas 2016-03-19 12:12:32 UTC
What behaviour are you expecting? Either that the enum is converted to a string or that the Vala compiler picks up the error in the template and stops?

You are using an enum in a Vala string template. There needs to be a method to convert the enum to a string. Vala has used a method of EnumClass, get_value() [1], but Soup.Message.tls_errors isn't an EnumClass.

For your program you will need to write code that converts the enum.

For Vala the issue appears to be how enums in templates should be handled.


[1] - https://developer.gnome.org/gobject/stable/gobject-Enumeration-and-Flag-Types.html#g-enum-get-value
Comment 4 Al Thomas 2016-03-19 12:41:42 UTC
Looking at this more closely you are using a string template expression: @"$(message.tls_errors)"

When using variable interpolation in the template:
@"$message.tls_errors"
then Vala does produce the expected error:
"error: The name `to_string' does not exist in the context of `Soup.Message'"

So the issue for Vala is how enums should be handled in string template expressions.
Comment 5 Marcin Lewandowski 2016-03-20 13:01:52 UTC
The reason why statically typed languages are often used for systems design is that they allow to catch such cases during the compilation time instead of crashing the system in the runtime. So if there's any way to detect such issue during compilaction time I strongly vote for issuing a compilation error.

My opinion was different if that had not been crashing the program but e.g. issuing a warning, but as long as it is crash possible to avoid during compile-time checks, it should be avoided at all cost.

I underline this given that difference in syntax and desired outcomes between string template expression and variable interpolation is very tiny, and it's totally non-intuitive that they have different behaviour.
Comment 6 Al Thomas 2016-03-21 21:56:43 UTC
There seems to be a lot going on within Vala and GLib here behind the scenes, so I will just report on my investigations so far in case anyone else wants to follow through.

The following Vala code:

void main() {
  ConverterResult a = ConverterResult.CONVERTED;
  print( @"String template variable: $a\n" );
  print( @"String template expression: $(a)\n" );
  print( "to_string() method: " + a.to_string() + "\n" );
  TlsCertificateFlags b = TlsCertificateFlags.UNKNOWN_CA;
  print( @"$(b)\n" );
}

when compiled and run will produce:

String template variable: G_CONVERTER_CONVERTED
String template expression: G_CONVERTER_CONVERTED
to_string() method: G_CONVERTER_CONVERTED
(process:16847): GLib-GObject-CRITICAL **: g_enum_get_value: assertion 'G_IS_ENUM_CLASS (enum_class)' failed
(null)

ConverterResult and TlsCertificateFlags are both defined as enums in https://git.gnome.org/browse/glib/tree/gio/gioenums.h and bound in https://git.gnome.org/browse/vala/tree/vapi/gio-2.0.vapi
The difference between the two is ConverterResult is an enum and TlsCertificateFlags are flags in Vala. TlsCertificateFlags is the value help in Soup.Message.tls_errors.

GLib provides an introspection mechanism for enums and flags, which I haven't fully understood yet: https://developer.gnome.org/gobject/stable/gobject-Enumeration-and-Flag-Types.html and https://developer.gnome.org/gobject/stable/glib-mkenums.html

By compiling the above code to C and changing

GEnumValue* _tmp9_;
to
GFlagsValue* _tmp9_;

and

_tmp9_ = g_enum_get_value (g_type_class_ref (g_tls_certificate_flags_get_type ()), b);
to
_tmp9_ = g_flags_get_first_value (g_type_class_ref (g_tls_certificate_flags_get_type ()), b);

when compiled and run will produce:
String template variable: G_CONVERTER_CONVERTED
String template expression: G_CONVERTER_CONVERTED
to_string() method: G_CONVERTER_CONVERTED
G_TLS_CERTIFICATE_UNKNOWN_CA

So clearly flags can be handled in a similar manner to enums.
Comment 7 therebedragons111 2016-08-20 10:10:31 UTC
Created attachment 333731 [details] [review]
patch solving the issue

Code visitor never checks if type is flags or not.

Good question is if g_enum_get_first_value is really what is wanted as it might be questionable in some cases. Trouble with flags is that sometimes you want to process them one by one and sometimes as whole.
Comment 8 Rico Tzschichholz 2016-09-16 16:44:03 UTC
Created attachment 335722 [details] [review]
codegen: Distinguish between Enum and Flags for their to_string()

This fixes a GLib-critical while using g_enum_get_value() on a GFlagsClass.
Therefore use g_flags_get_first_value() if needed.

Patch by therebedragons111
Comment 9 Rico Tzschichholz 2016-09-16 16:44:53 UTC
Attachment 335722 [details] pushed as de38563 - codegen: Distinguish between Enum and Flags for their to_string()