Skip to content

Commit

Permalink
iio_adi_xflow_check: Fix getopt() handling
Browse files Browse the repository at this point in the history
iio_adi_xflow_check currently assumes that the argument for an option that
is parsed by getopt_long() is in the argv[] following the option and then
the combination of option and argument always consumes two argv[] entries.

This is not necessarily true though. getopt_long() accepts option and
argument in the same argv[] entry. For short options the argument can
directly follow the option character and for long options the argument can
follow in the same argv[] entry separated by a '=' character.

E.g. both -u ip:192.168.1.1 and -uip:192.168.1.1 as well as --uri
192.168.1.1 and --uri=192.168.1.1 are equivalent and all valid.

As a result of this iio_adi_xflow_check will show undefined behavior when
option and argument are passed in the same argv[] entry (E.g. crash with a
segmentation fault).

To address this properly use the optarg and optind variables that are
provided by the getopt() interface. optarg points to the start of the
argument for the current option and optind will point to the first non
option argv[] entry after all options have been scanned.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
  • Loading branch information
larsclausen authored and commodo committed Feb 28, 2018
1 parent f5d8ddc commit 989db5e
Showing 1 changed file with 12 additions and 14 deletions.
26 changes: 12 additions & 14 deletions tests/iio_adi_xflow_check.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,9 @@ static struct iio_context *scan(void)
int main(int argc, char **argv)
{
unsigned int buffer_size = 1024 * 1024;
int c, option_index = 0, arg_index = 0, ip_index = 0, uri_index = 0;
int c, option_index = 0;
const char *arg_uri = NULL;
const char *arg_ip = NULL;
unsigned int n_tx = 0, n_rx = 0;
static struct iio_context *ctx;
static struct xflow_pthread_data xflow_pthread_data;
Expand All @@ -220,8 +222,7 @@ int main(int argc, char **argv)
usage(argv);
return EXIT_SUCCESS;
case 's':
arg_index += 2;
ret = sscanf(argv[arg_index], "%u%c", &buffer_size, &unit);
ret = sscanf(optarg, "%u%c", &buffer_size, &unit);
if (ret == 0)
return EXIT_FAILURE;
if (ret == 2) {
Expand All @@ -232,23 +233,20 @@ int main(int argc, char **argv)
}
break;
case 'n':
arg_index += 2;
ip_index = arg_index;
arg_ip = optarg;
break;
case 'u':
arg_index += 2;
uri_index = arg_index;
arg_uri = optarg;
break;
case 'a':
arg_index += 1;
scan_for_context = true;
break;
case '?':
return EXIT_FAILURE;
}
}

if (arg_index + 1 >= argc) {
if (optind + 1 != argc) {
fprintf(stderr, "Incorrect number of arguments.\n\n");
usage(argv);
return EXIT_FAILURE;
Expand All @@ -264,10 +262,10 @@ int main(int argc, char **argv)

if (scan_for_context)
ctx = scan();
else if (uri_index)
ctx = iio_create_context_from_uri(argv[uri_index]);
else if (ip_index)
ctx = iio_create_network_context(argv[ip_index]);
else if (arg_uri)
ctx = iio_create_context_from_uri(arg_uri);
else if (arg_ip)
ctx = iio_create_network_context(arg_ip);
else
ctx = iio_create_default_context();

Expand All @@ -276,7 +274,7 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
}

device_name = argv[arg_index + 1];
device_name = argv[optind];

dev = get_device(ctx, device_name);
if (!dev) {
Expand Down

0 comments on commit 989db5e

Please sign in to comment.