[git commit] i2cset: fix 'i' & 's' modes (3 extra bytes were sent)

Denys Vlasenko vda.linux at googlemail.com
Thu Oct 5 09:25:16 UTC 2017


commit: https://git.busybox.net/busybox/commit/?id=b5d9ba8fe64a0aacf99fd1eec10375a98104a5ea
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

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 at gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 miscutils/i2c_tools.c | 40 +++++++++++++++++++++++++++-------------
 1 file changed, 27 insertions(+), 13 deletions(-)

diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c
index fc392d9..82f9842 100644
--- a/miscutils/i2c_tools.c
+++ b/miscutils/i2c_tools.c
@@ -562,14 +562,19 @@ int i2cset_main(int argc, char **argv)
 			      opt_m = (1 << 2), opt_r = (1 << 3);
 
 	int bus_num, bus_addr, data_addr, mode = I2C_SMBUS_BYTE, pec = 0;
-	int val, blen = 0, mask = 0, fd, status;
+	int val, blen, mask, fd, status;
 	unsigned char block[I2C_SMBUS_BLOCK_MAX];
 	char *opt_m_arg = NULL;
 	unsigned opts;
 
-	opts = getopt32(argv, "^" "fym:r" "\0" "-3"/*from 3 to ? args*/, &opt_m_arg);
+	opts = getopt32(argv, "^"
+		"fym:r"
+		"\0" "-3", /* minimum 3 args */
+		&opt_m_arg
+	);
 	argv += optind;
 	argc -= optind;
+	argc--; /* now argv[argc] is last arg */
 
 	bus_num = i2c_bus_lookup(argv[0]);
 	bus_addr = i2c_parse_bus_addr(argv[1]);
@@ -579,20 +584,26 @@ int i2cset_main(int argc, char **argv)
 		if (!argv[4] && argv[3][0] != 'c') {
 			mode = I2C_SMBUS_BYTE_DATA; /* Implicit b */
 		} else {
-			switch (argv[argc-1][0]) {
-			case 'c': /* Already set */			break;
-			case 'b': mode = I2C_SMBUS_BYTE_DATA;		break;
-			case 'w': mode = I2C_SMBUS_WORD_DATA;		break;
-			case 's': mode = I2C_SMBUS_BLOCK_DATA;		break;
-			case 'i': mode = I2C_SMBUS_I2C_BLOCK_DATA;	break;
+			switch (argv[argc][0]) {
+			case 'c': /* Already set */
+				break;
+			case 'b': mode = I2C_SMBUS_BYTE_DATA;
+				break;
+			case 'w': mode = I2C_SMBUS_WORD_DATA;
+				break;
+			case 's': mode = I2C_SMBUS_BLOCK_DATA;
+				break;
+			case 'i': mode = I2C_SMBUS_I2C_BLOCK_DATA;
+				break;
 			default:
 				bb_error_msg("invalid mode");
 				bb_show_usage();
 			}
 
-			pec = argv[argc-1][1] == 'p';
-			if (mode == I2C_SMBUS_BLOCK_DATA ||
-					mode == I2C_SMBUS_I2C_BLOCK_DATA) {
+			pec = (argv[argc][1] == 'p');
+			if (mode == I2C_SMBUS_BLOCK_DATA
+			 || mode == I2C_SMBUS_I2C_BLOCK_DATA
+			) {
 				if (pec && mode == I2C_SMBUS_I2C_BLOCK_DATA)
 					bb_error_msg_and_die(
 						"PEC not supported for I2C "
@@ -606,6 +617,8 @@ int i2cset_main(int argc, char **argv)
 	}
 
 	/* Prepare the value(s) to be written according to current mode. */
+	mask = 0;
+	blen = 0;
 	switch (mode) {
 	case I2C_SMBUS_BYTE_DATA:
 		val = xstrtou_range(argv[3], 0, 0, 0xff);
@@ -615,8 +628,9 @@ int i2cset_main(int argc, char **argv)
 		break;
 	case I2C_SMBUS_BLOCK_DATA:
 	case I2C_SMBUS_I2C_BLOCK_DATA:
-		for (blen = 3; blen < (argc - 1); blen++)
-			block[blen] = xstrtou_range(argv[blen], 0, 0, 0xff);
+		for (blen = 3; blen < argc; blen++)
+			block[blen - 3] = xstrtou_range(argv[blen], 0, 0, 0xff);
+		blen -= 3;
 		val = -1;
 		break;
 	default:


More information about the busybox-cvs mailing list