diff options
author | Avi Fishman <AviFishman70@gmail.com> | 2017-10-05 11:25:16 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-10-05 11:25:16 +0200 |
commit | b5d9ba8fe64a0aacf99fd1eec10375a98104a5ea (patch) | |
tree | 814c48b7c5a35fbb141fb8be939f17b3145d9307 | |
parent | 6f97b30a904407c1f1701d937d9258ca9175c6ab (diff) | |
download | busybox-w32-b5d9ba8fe64a0aacf99fd1eec10375a98104a5ea.tar.gz busybox-w32-b5d9ba8fe64a0aacf99fd1eec10375a98104a5ea.tar.bz2 busybox-w32-b5d9ba8fe64a0aacf99fd1eec10375a98104a5ea.zip |
i2cset: fix 'i' & 's' modes (3 extra bytes were sent)
When 'i' or 's' modes are selected block array is filled from offset 3
(blen = 3) but copied to data.block buffer from offset 0 so first 3 bytes
contains garbage from stack.
The buffer that is sent is also 3 bytes too long due to those extra 3
bytes.
Signed-off-by: Avi Fishman <AviFishman70@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | miscutils/i2c_tools.c | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index fc392d9dc..82f9842bd 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c | |||
@@ -562,14 +562,19 @@ int i2cset_main(int argc, char **argv) | |||
562 | opt_m = (1 << 2), opt_r = (1 << 3); | 562 | opt_m = (1 << 2), opt_r = (1 << 3); |
563 | 563 | ||
564 | int bus_num, bus_addr, data_addr, mode = I2C_SMBUS_BYTE, pec = 0; | 564 | int bus_num, bus_addr, data_addr, mode = I2C_SMBUS_BYTE, pec = 0; |
565 | int val, blen = 0, mask = 0, fd, status; | 565 | int val, blen, mask, fd, status; |
566 | unsigned char block[I2C_SMBUS_BLOCK_MAX]; | 566 | unsigned char block[I2C_SMBUS_BLOCK_MAX]; |
567 | char *opt_m_arg = NULL; | 567 | char *opt_m_arg = NULL; |
568 | unsigned opts; | 568 | unsigned opts; |
569 | 569 | ||
570 | opts = getopt32(argv, "^" "fym:r" "\0" "-3"/*from 3 to ? args*/, &opt_m_arg); | 570 | opts = getopt32(argv, "^" |
571 | "fym:r" | ||
572 | "\0" "-3", /* minimum 3 args */ | ||
573 | &opt_m_arg | ||
574 | ); | ||
571 | argv += optind; | 575 | argv += optind; |
572 | argc -= optind; | 576 | argc -= optind; |
577 | argc--; /* now argv[argc] is last arg */ | ||
573 | 578 | ||
574 | bus_num = i2c_bus_lookup(argv[0]); | 579 | bus_num = i2c_bus_lookup(argv[0]); |
575 | bus_addr = i2c_parse_bus_addr(argv[1]); | 580 | bus_addr = i2c_parse_bus_addr(argv[1]); |
@@ -579,20 +584,26 @@ int i2cset_main(int argc, char **argv) | |||
579 | if (!argv[4] && argv[3][0] != 'c') { | 584 | if (!argv[4] && argv[3][0] != 'c') { |
580 | mode = I2C_SMBUS_BYTE_DATA; /* Implicit b */ | 585 | mode = I2C_SMBUS_BYTE_DATA; /* Implicit b */ |
581 | } else { | 586 | } else { |
582 | switch (argv[argc-1][0]) { | 587 | switch (argv[argc][0]) { |
583 | case 'c': /* Already set */ break; | 588 | case 'c': /* Already set */ |
584 | case 'b': mode = I2C_SMBUS_BYTE_DATA; break; | 589 | break; |
585 | case 'w': mode = I2C_SMBUS_WORD_DATA; break; | 590 | case 'b': mode = I2C_SMBUS_BYTE_DATA; |
586 | case 's': mode = I2C_SMBUS_BLOCK_DATA; break; | 591 | break; |
587 | case 'i': mode = I2C_SMBUS_I2C_BLOCK_DATA; break; | 592 | case 'w': mode = I2C_SMBUS_WORD_DATA; |
593 | break; | ||
594 | case 's': mode = I2C_SMBUS_BLOCK_DATA; | ||
595 | break; | ||
596 | case 'i': mode = I2C_SMBUS_I2C_BLOCK_DATA; | ||
597 | break; | ||
588 | default: | 598 | default: |
589 | bb_error_msg("invalid mode"); | 599 | bb_error_msg("invalid mode"); |
590 | bb_show_usage(); | 600 | bb_show_usage(); |
591 | } | 601 | } |
592 | 602 | ||
593 | pec = argv[argc-1][1] == 'p'; | 603 | pec = (argv[argc][1] == 'p'); |
594 | if (mode == I2C_SMBUS_BLOCK_DATA || | 604 | if (mode == I2C_SMBUS_BLOCK_DATA |
595 | mode == I2C_SMBUS_I2C_BLOCK_DATA) { | 605 | || mode == I2C_SMBUS_I2C_BLOCK_DATA |
606 | ) { | ||
596 | if (pec && mode == I2C_SMBUS_I2C_BLOCK_DATA) | 607 | if (pec && mode == I2C_SMBUS_I2C_BLOCK_DATA) |
597 | bb_error_msg_and_die( | 608 | bb_error_msg_and_die( |
598 | "PEC not supported for I2C " | 609 | "PEC not supported for I2C " |
@@ -606,6 +617,8 @@ int i2cset_main(int argc, char **argv) | |||
606 | } | 617 | } |
607 | 618 | ||
608 | /* Prepare the value(s) to be written according to current mode. */ | 619 | /* Prepare the value(s) to be written according to current mode. */ |
620 | mask = 0; | ||
621 | blen = 0; | ||
609 | switch (mode) { | 622 | switch (mode) { |
610 | case I2C_SMBUS_BYTE_DATA: | 623 | case I2C_SMBUS_BYTE_DATA: |
611 | val = xstrtou_range(argv[3], 0, 0, 0xff); | 624 | val = xstrtou_range(argv[3], 0, 0, 0xff); |
@@ -615,8 +628,9 @@ int i2cset_main(int argc, char **argv) | |||
615 | break; | 628 | break; |
616 | case I2C_SMBUS_BLOCK_DATA: | 629 | case I2C_SMBUS_BLOCK_DATA: |
617 | case I2C_SMBUS_I2C_BLOCK_DATA: | 630 | case I2C_SMBUS_I2C_BLOCK_DATA: |
618 | for (blen = 3; blen < (argc - 1); blen++) | 631 | for (blen = 3; blen < argc; blen++) |
619 | block[blen] = xstrtou_range(argv[blen], 0, 0, 0xff); | 632 | block[blen - 3] = xstrtou_range(argv[blen], 0, 0, 0xff); |
633 | blen -= 3; | ||
620 | val = -1; | 634 | val = -1; |
621 | break; | 635 | break; |
622 | default: | 636 | default: |