mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-07 13:08:10 +02:00
cli: fix handling uint64 connection property "serial.send-delay"
libnm currently has only one GObject property of type uint64:
"serial.send-delay". However, it's broken because uint64 handling
is not implemented.
$ nmcli connection add type gsm autoconnect no con-name t ifname '*' apn 'xyz' serial.baud 5
Connection 't' (4c929f17-9fda-41d6-8f90-897f6d46b078) successfully added.
$ nmcli connection show t
...
ipv6.dhcp-duid: --
ipv6.dhcp-send-hostname: yes
ipv6.dhcp-hostname: --
ipv6.token: --
(process:14016): libnmc-CRITICAL **: 14:08:32.591: file clients/common/nm-meta-setting-desc.c: line 811 (_get_fcn_gobject_int): should not be reached
serial.baud: 5
serial.bits: 8
serial.parity: none
serial.stopbits: 1
serial.send-delay: --
gsm.number: *99#
...
$ nmcli connection add type gsm autoconnect no con-name t ifname '*' apn 'xyz' serial.baud 5 serial.send-delay 100
(process:14852): libnmc-CRITICAL **: 14:12:24.259: file clients/common/nm-meta-setting-desc.c: line 1131 (_set_fcn_gobject_int): should not be reached
Segmentation fault (core dumped)
Fixes: b6d9bdcee8
(cherry picked from commit a600b3a3b2)
(cherry picked from commit 1b987a5366)
This commit is contained in:
parent
8cb0a13a5b
commit
cf482ae8ee
2 changed files with 104 additions and 60 deletions
|
|
@ -783,7 +783,8 @@ _get_fcn_gobject_int (ARGS_GET_FCN)
|
||||||
{
|
{
|
||||||
GParamSpec *pspec;
|
GParamSpec *pspec;
|
||||||
nm_auto_unset_gvalue GValue gval = G_VALUE_INIT;
|
nm_auto_unset_gvalue GValue gval = G_VALUE_INIT;
|
||||||
gint64 v;
|
gboolean is_uint64 = FALSE;
|
||||||
|
NMMetaSignUnsignInt64 v;
|
||||||
guint base = 10;
|
guint base = 10;
|
||||||
const NMMetaUtilsIntValueInfo *value_infos;
|
const NMMetaUtilsIntValueInfo *value_infos;
|
||||||
char *return_str;
|
char *return_str;
|
||||||
|
|
@ -799,13 +800,18 @@ _get_fcn_gobject_int (ARGS_GET_FCN)
|
||||||
NM_SET_OUT (out_is_default, g_param_value_defaults (pspec, &gval));
|
NM_SET_OUT (out_is_default, g_param_value_defaults (pspec, &gval));
|
||||||
switch (pspec->value_type) {
|
switch (pspec->value_type) {
|
||||||
case G_TYPE_INT:
|
case G_TYPE_INT:
|
||||||
v = g_value_get_int (&gval);
|
v.i64 = g_value_get_int (&gval);
|
||||||
break;
|
break;
|
||||||
case G_TYPE_UINT:
|
case G_TYPE_UINT:
|
||||||
v = g_value_get_uint (&gval);
|
v.u64 = g_value_get_uint (&gval);
|
||||||
|
is_uint64 = TRUE;
|
||||||
break;
|
break;
|
||||||
case G_TYPE_INT64:
|
case G_TYPE_INT64:
|
||||||
v = g_value_get_int64 (&gval);
|
v.i64 = g_value_get_int64 (&gval);
|
||||||
|
break;
|
||||||
|
case G_TYPE_UINT64:
|
||||||
|
v.u64 = g_value_get_uint64 (&gval);
|
||||||
|
is_uint64 = TRUE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_return_val_if_reached (NULL);
|
g_return_val_if_reached (NULL);
|
||||||
|
|
@ -819,10 +825,16 @@ _get_fcn_gobject_int (ARGS_GET_FCN)
|
||||||
|
|
||||||
switch (base) {
|
switch (base) {
|
||||||
case 10:
|
case 10:
|
||||||
return_str = g_strdup_printf ("%"G_GINT64_FORMAT, v);
|
if (is_uint64)
|
||||||
|
return_str = g_strdup_printf ("%"G_GUINT64_FORMAT, v.u64);
|
||||||
|
else
|
||||||
|
return_str = g_strdup_printf ("%"G_GINT64_FORMAT, v.i64);
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
return_str = g_strdup_printf ("0x%"G_GINT64_MODIFIER"x", v);
|
if (is_uint64)
|
||||||
|
return_str = g_strdup_printf ("0x%"G_GINT64_MODIFIER"x", v.u64);
|
||||||
|
else
|
||||||
|
return_str = g_strdup_printf ("0x%"G_GINT64_MODIFIER"x", (guint64) v.i64);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return_str = NULL;
|
return_str = NULL;
|
||||||
|
|
@ -833,7 +845,8 @@ _get_fcn_gobject_int (ARGS_GET_FCN)
|
||||||
&& property_info->property_typ_data
|
&& property_info->property_typ_data
|
||||||
&& (value_infos = property_info->property_typ_data->subtype.gobject_int.value_infos)) {
|
&& (value_infos = property_info->property_typ_data->subtype.gobject_int.value_infos)) {
|
||||||
for (; value_infos->nick; value_infos++) {
|
for (; value_infos->nick; value_infos++) {
|
||||||
if (value_infos->value == v) {
|
if ( ( is_uint64 && value_infos->value.u64 == v.u64)
|
||||||
|
|| (!is_uint64 && value_infos->value.i64 == v.i64)) {
|
||||||
char *old_str = return_str;
|
char *old_str = return_str;
|
||||||
|
|
||||||
return_str = g_strdup_printf ("%s (%s)", old_str, value_infos->nick);
|
return_str = g_strdup_printf ("%s (%s)", old_str, value_infos->nick);
|
||||||
|
|
@ -1060,16 +1073,21 @@ _set_fcn_gobject_int (ARGS_SET_FCN)
|
||||||
int errsv;
|
int errsv;
|
||||||
const GParamSpec *pspec;
|
const GParamSpec *pspec;
|
||||||
nm_auto_unset_gvalue GValue gval = G_VALUE_INIT;
|
nm_auto_unset_gvalue GValue gval = G_VALUE_INIT;
|
||||||
gint64 v = 0;
|
gboolean is_uint64;
|
||||||
|
NMMetaSignUnsignInt64 v;
|
||||||
gboolean has_minmax = FALSE;
|
gboolean has_minmax = FALSE;
|
||||||
gint64 min = G_MININT64;
|
NMMetaSignUnsignInt64 min = { 0 };
|
||||||
gint64 max = G_MAXINT64;
|
NMMetaSignUnsignInt64 max = { 0 };
|
||||||
guint base = 10;
|
guint base = 10;
|
||||||
const NMMetaUtilsIntValueInfo *value_infos = NULL;
|
const NMMetaUtilsIntValueInfo *value_infos;
|
||||||
gboolean has_value = FALSE;
|
|
||||||
|
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (setting)), property_info->property_name);
|
||||||
|
if (!G_IS_PARAM_SPEC (pspec))
|
||||||
|
g_return_val_if_reached (FALSE);
|
||||||
|
|
||||||
|
is_uint64 = NM_IN_SET (pspec->value_type, G_TYPE_UINT, G_TYPE_UINT64);
|
||||||
|
|
||||||
if (property_info->property_typ_data) {
|
if (property_info->property_typ_data) {
|
||||||
|
|
||||||
if ( value
|
if ( value
|
||||||
&& (value_infos = property_info->property_typ_data->subtype.gobject_int.value_infos)) {
|
&& (value_infos = property_info->property_typ_data->subtype.gobject_int.value_infos)) {
|
||||||
gs_free char *vv_stripped = NULL;
|
gs_free char *vv_stripped = NULL;
|
||||||
|
|
@ -1083,85 +1101,106 @@ _set_fcn_gobject_int (ARGS_SET_FCN)
|
||||||
for (; value_infos->nick; value_infos++) {
|
for (; value_infos->nick; value_infos++) {
|
||||||
if (nm_streq (value_infos->nick, vv)) {
|
if (nm_streq (value_infos->nick, vv)) {
|
||||||
v = value_infos->value;
|
v = value_infos->value;
|
||||||
has_value = TRUE;
|
goto have_value_from_nick;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (property_info->property_typ_data->subtype.gobject_int.base > 0)
|
if (property_info->property_typ_data->subtype.gobject_int.base > 0)
|
||||||
base = property_info->property_typ_data->subtype.gobject_int.base;
|
base = property_info->property_typ_data->subtype.gobject_int.base;
|
||||||
if ( property_info->property_typ_data->subtype.gobject_int.min
|
|
||||||
|| property_info->property_typ_data->subtype.gobject_int.max) {
|
if ( ( is_uint64
|
||||||
|
&& ( property_info->property_typ_data->subtype.gobject_int.min.u64
|
||||||
|
|| property_info->property_typ_data->subtype.gobject_int.max.u64))
|
||||||
|
|| ( !is_uint64
|
||||||
|
&& ( property_info->property_typ_data->subtype.gobject_int.min.i64
|
||||||
|
|| property_info->property_typ_data->subtype.gobject_int.max.i64))) {
|
||||||
min = property_info->property_typ_data->subtype.gobject_int.min;
|
min = property_info->property_typ_data->subtype.gobject_int.min;
|
||||||
max = property_info->property_typ_data->subtype.gobject_int.max;
|
max = property_info->property_typ_data->subtype.gobject_int.max;
|
||||||
has_minmax = TRUE;
|
has_minmax = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (setting)), property_info->property_name);
|
if (!has_minmax) {
|
||||||
if (!G_IS_PARAM_SPEC (pspec))
|
switch (pspec->value_type) {
|
||||||
g_return_val_if_reached (FALSE);
|
case G_TYPE_INT:
|
||||||
switch (pspec->value_type) {
|
{
|
||||||
case G_TYPE_INT:
|
const GParamSpecInt *p = (GParamSpecInt *) pspec;
|
||||||
if (!has_minmax) {
|
|
||||||
const GParamSpecInt *p = (GParamSpecInt *) pspec;
|
|
||||||
|
|
||||||
min = p->minimum;
|
min.i64 = p->minimum;
|
||||||
max = p->maximum;
|
max.i64 = p->maximum;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case G_TYPE_UINT:
|
case G_TYPE_UINT:
|
||||||
if (!has_minmax) {
|
{
|
||||||
const GParamSpecUInt *p = (GParamSpecUInt *) pspec;
|
const GParamSpecUInt *p = (GParamSpecUInt *) pspec;
|
||||||
|
|
||||||
min = p->minimum;
|
min.u64 = p->minimum;
|
||||||
max = p->maximum;
|
max.u64 = p->maximum;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case G_TYPE_INT64:
|
case G_TYPE_INT64:
|
||||||
if (!has_minmax) {
|
{
|
||||||
const GParamSpecInt64 *p = (GParamSpecInt64 *) pspec;
|
const GParamSpecInt64 *p = (GParamSpecInt64 *) pspec;
|
||||||
|
|
||||||
min = p->minimum;
|
min.i64 = p->minimum;
|
||||||
max = p->maximum;
|
max.i64 = p->maximum;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case G_TYPE_UINT64:
|
||||||
|
{
|
||||||
|
const GParamSpecUInt64 *p = (GParamSpecUInt64 *) pspec;
|
||||||
|
|
||||||
|
min.u64 = p->minimum;
|
||||||
|
max.u64 = p->maximum;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_return_val_if_reached (FALSE);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
default:
|
|
||||||
g_return_val_if_reached (FALSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!has_value) {
|
if (is_uint64)
|
||||||
v = _nm_utils_ascii_str_to_int64 (value, base, min, max, 0);
|
v.u64 = _nm_utils_ascii_str_to_uint64 (value, base, min.u64, max.u64, 0);
|
||||||
|
else
|
||||||
|
v.i64 = _nm_utils_ascii_str_to_int64 (value, base, min.i64, max.i64, 0);
|
||||||
|
|
||||||
if ((errsv = errno) != 0) {
|
if ((errsv = errno) != 0) {
|
||||||
if (errsv == ERANGE) {
|
if (errsv == ERANGE) {
|
||||||
|
if (is_uint64) {
|
||||||
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT,
|
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT,
|
||||||
_("'%s' is out of range [%lli, %lli]"),
|
_("'%s' is out of range [%"G_GUINT64_FORMAT", %"G_GUINT64_FORMAT"]"),
|
||||||
value,
|
value, min.u64, max.u64);
|
||||||
(long long) min,
|
|
||||||
(long long) max);
|
|
||||||
} else {
|
} else {
|
||||||
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT,
|
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT,
|
||||||
_("'%s' is not a valid number"), value);
|
_("'%s' is out of range [%"G_GINT64_FORMAT", %"G_GINT64_FORMAT"]"),
|
||||||
|
value, min.i64, max.i64);
|
||||||
}
|
}
|
||||||
return FALSE;
|
} else {
|
||||||
|
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT,
|
||||||
|
_("'%s' is not a valid number"), value);
|
||||||
}
|
}
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
have_value_from_nick:
|
||||||
|
|
||||||
g_value_init (&gval, pspec->value_type);
|
g_value_init (&gval, pspec->value_type);
|
||||||
switch (pspec->value_type) {
|
switch (pspec->value_type) {
|
||||||
case G_TYPE_INT:
|
case G_TYPE_INT:
|
||||||
g_value_set_int (&gval, v);
|
g_value_set_int (&gval, v.i64);
|
||||||
break;
|
break;
|
||||||
case G_TYPE_UINT:
|
case G_TYPE_UINT:
|
||||||
g_value_set_uint (&gval, v);
|
g_value_set_uint (&gval, v.u64);
|
||||||
break;
|
break;
|
||||||
case G_TYPE_INT64:
|
case G_TYPE_INT64:
|
||||||
g_value_set_int64 (&gval, v);
|
g_value_set_int64 (&gval, v.i64);
|
||||||
|
break;
|
||||||
|
case G_TYPE_UINT64:
|
||||||
|
g_value_set_uint64 (&gval, v.u64);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
nm_assert_not_reached ();
|
g_return_val_if_reached (FALSE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -225,9 +225,14 @@ struct _NMMetaPropertyType {
|
||||||
|
|
||||||
struct _NMUtilsEnumValueInfo;
|
struct _NMUtilsEnumValueInfo;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
gint64 i64;
|
||||||
|
guint64 u64;
|
||||||
|
} NMMetaSignUnsignInt64;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *nick;
|
const char *nick;
|
||||||
gint64 value;
|
NMMetaSignUnsignInt64 value;
|
||||||
} NMMetaUtilsIntValueInfo;
|
} NMMetaUtilsIntValueInfo;
|
||||||
|
|
||||||
struct _NMMetaPropertyTypData {
|
struct _NMMetaPropertyTypData {
|
||||||
|
|
@ -248,8 +253,8 @@ struct _NMMetaPropertyTypData {
|
||||||
int value);
|
int value);
|
||||||
} gobject_enum;
|
} gobject_enum;
|
||||||
struct {
|
struct {
|
||||||
gint64 min;
|
NMMetaSignUnsignInt64 min;
|
||||||
gint64 max;
|
NMMetaSignUnsignInt64 max;
|
||||||
guint base;
|
guint base;
|
||||||
const NMMetaUtilsIntValueInfo *value_infos;
|
const NMMetaUtilsIntValueInfo *value_infos;
|
||||||
} gobject_int;
|
} gobject_int;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue