]> sigrok.org Git - libsigrok.git/commitdiff
drivers: Fix locale dependent string to float conversion
authorFrank Stettner <redacted>
Thu, 2 Nov 2017 17:04:59 +0000 (18:04 +0100)
committerUwe Hermann <redacted>
Sat, 11 Nov 2017 18:46:52 +0000 (19:46 +0100)
Some drivers used locale dependent functions for converting strings
to float/double values. These functions fail when the decimal mark
is a "," in the locale settings but the string contains a ".".

This fixes bug #1064.

src/dmm/m2110.c
src/dmm/metex14.c
src/hardware/motech-lps-30x/protocol.c
src/libsigrok-internal.h
src/scpi/scpi.c
src/strutil.c

index fc09276561b6e60b134e2438b7c3a79f4605a40d..4f3af6940c062e2a9a28aa12e09a14f2fab9f613 100644 (file)
@@ -44,7 +44,7 @@ SR_PRIV gboolean sr_m2110_packet_valid(const uint8_t *buf)
        if (!strncmp((const char *)buf, "OVERRNG", 7))
                return TRUE;
 
-       if (sscanf((const char *)buf, "%f", &val) == 1)
+       if (sr_atof_ascii((const char *)buf, &val) == SR_OK)
                return TRUE;
        else
                return FALSE;
@@ -65,7 +65,7 @@ SR_PRIV int sr_m2110_parse(const uint8_t *buf, float *floatval,
 
        if (!strncmp((const char *)buf, "OVERRNG", 7))
                *floatval = INFINITY;
-       else if (sscanf((const char *)buf, "%f", &val) == 1) {
+       else if (sr_atof_ascii((const char *)buf, &val) == SR_OK) {
                *floatval = val;
                dot_pos = strcspn((const char *)buf, ".");
                if (dot_pos < 7)
index 65a3f1fe78a481c47509ab33c1a701dac216cd26..0dd5d2edc8602dada2c4c24666bf818f239d46c2 100644 (file)
@@ -86,7 +86,7 @@ static int parse_value(const uint8_t *buf, struct metex14_info *info,
                return SR_OK;
 
        /* Bytes 2-8: Sign, value (up to 5 digits) and decimal point */
-       sscanf((const char *)&valstr, "%f", result);
+       sr_atof_ascii((const char *)&valstr, result);
 
        dot_pos = strcspn(valstr, ".");
        if (dot_pos < cnt)
index c952ed0bc6bf7b91f02a20ef8369b2ff93336a65..ce097274428fc2f472c015dc6f4bd6c8b00c16bc 100644 (file)
@@ -87,7 +87,7 @@ static void process_line(struct sr_dev_inst *sdi)
                case AQ_U2:
                case AQ_I1:
                case AQ_I2:
-                       if (sr_atod(devc->buf, &dbl) != SR_OK) {
+                       if (sr_atod_ascii(devc->buf, &dbl) != SR_OK) {
                                sr_err("Failed to convert '%s' to double, errno=%d %s",
                                        devc->buf, errno, g_strerror(errno));
                                dbl = 0.0;
index 044aa9da72634792268450fade11cb4e5de1b974..9fdd81dac4c26310614f1f2a22307ec7ba572444 100644 (file)
@@ -1010,6 +1010,7 @@ SR_PRIV int sr_atol(const char *str, long *ret);
 SR_PRIV int sr_atoi(const char *str, int *ret);
 SR_PRIV int sr_atod(const char *str, double *ret);
 SR_PRIV int sr_atof(const char *str, float *ret);
+SR_PRIV int sr_atod_ascii(const char *str, double *ret);
 SR_PRIV int sr_atof_ascii(const char *str, float *ret);
 
 /*--- soft-trigger.c --------------------------------------------------------*/
index 84335408a70ef77a4ddd09c1f96fa75bf736a6c3..511e3cd20bc6e56eca6d711e30991ae00046d1a4 100644 (file)
@@ -627,7 +627,7 @@ SR_PRIV int sr_scpi_get_double(struct sr_scpi_dev_inst *scpi,
        if (ret != SR_OK && !response)
                return ret;
 
-       if (sr_atod(response, scpi_response) == SR_OK)
+       if (sr_atod_ascii(response, scpi_response) == SR_OK)
                ret = SR_OK;
        else
                ret = SR_ERR_DATA;
index 5f0deb7708f374327b6c5d33e7649ca3da342948..30e992b815468e5a86c1210652b3a19aece2720b 100644 (file)
@@ -169,6 +169,38 @@ SR_PRIV int sr_atof(const char *str, float *ret)
        return SR_OK;
 }
 
+/**
+ * @private
+ *
+ * Convert a string representation of a numeric value to a double. The
+ * conversion is strict and will fail if the complete string does not represent
+ * a valid double. The function sets errno according to the details of the
+ * failure. This version ignores the locale.
+ *
+ * @param str The string representation to convert.
+ * @param ret Pointer to double where the result of the conversion will be stored.
+ *
+ * @retval SR_OK Conversion successful.
+ * @retval SR_ERR Failure.
+ */
+SR_PRIV int sr_atod_ascii(const char *str, double *ret)
+{
+       double tmp;
+       char *endptr = NULL;
+
+       errno = 0;
+       tmp = g_ascii_strtod(str, &endptr);
+
+       if (!endptr || *endptr || errno) {
+               if (!errno)
+                       errno = EINVAL;
+               return SR_ERR;
+       }
+
+       *ret = tmp;
+       return SR_OK;
+}
+
 /**
  * @private
  *