Commit f3651764e57e353251695691677bd95ba5a420bc
Committed by
Wolfgang Denk
1 parent
0ad22703f0
Exists in
master
and in
54 other branches
cmd_itest.c: fix pointer dereferencing
fix pointer dereferencing if the size is .b and .w an 8 or 16 bit access is done. Signed-off-by: Frans Meulenbroeks <fransmeulenbroeks@gmail.com> Acked-by: Detlev Zundel <dzu@denx.de>
Showing 1 changed file with 7 additions and 2 deletions Inline Diff
common/cmd_itest.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2003 | 2 | * (C) Copyright 2003 |
3 | * Tait Electronics Limited, Christchurch, New Zealand | 3 | * Tait Electronics Limited, Christchurch, New Zealand |
4 | * | 4 | * |
5 | * See file CREDITS for list of people who contributed to this | 5 | * See file CREDITS for list of people who contributed to this |
6 | * project. | 6 | * project. |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License as | 9 | * modify it under the terms of the GNU General Public License as |
10 | * published by the Free Software Foundation; either version 2 of | 10 | * published by the Free Software Foundation; either version 2 of |
11 | * the License, or (at your option) any later version. | 11 | * the License, or (at your option) any later version. |
12 | * | 12 | * |
13 | * This program is distributed in the hope that it will be useful, | 13 | * This program is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
17 | * | 17 | * |
18 | * You should have received a copy of the GNU General Public License | 18 | * You should have received a copy of the GNU General Public License |
19 | * along with this program; if not, write to the Free Software | 19 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
21 | * MA 02111-1307 USA | 21 | * MA 02111-1307 USA |
22 | */ | 22 | */ |
23 | 23 | ||
24 | /* | 24 | /* |
25 | * This file provides a shell like 'test' function to return | 25 | * This file provides a shell like 'test' function to return |
26 | * true/false from an integer or string compare of two memory | 26 | * true/false from an integer or string compare of two memory |
27 | * locations or a location and a scalar/literal. | 27 | * locations or a location and a scalar/literal. |
28 | * A few parts were lifted from bash 'test' command | 28 | * A few parts were lifted from bash 'test' command |
29 | */ | 29 | */ |
30 | 30 | ||
31 | #include <common.h> | 31 | #include <common.h> |
32 | #include <config.h> | 32 | #include <config.h> |
33 | #include <command.h> | 33 | #include <command.h> |
34 | 34 | ||
35 | #define EQ 0 | 35 | #define EQ 0 |
36 | #define NE 1 | 36 | #define NE 1 |
37 | #define LT 2 | 37 | #define LT 2 |
38 | #define GT 3 | 38 | #define GT 3 |
39 | #define LE 4 | 39 | #define LE 4 |
40 | #define GE 5 | 40 | #define GE 5 |
41 | 41 | ||
42 | struct op_tbl_s { | 42 | struct op_tbl_s { |
43 | char *op; /* operator string */ | 43 | char *op; /* operator string */ |
44 | int opcode; /* internal representation of opcode */ | 44 | int opcode; /* internal representation of opcode */ |
45 | }; | 45 | }; |
46 | 46 | ||
47 | typedef struct op_tbl_s op_tbl_t; | 47 | typedef struct op_tbl_s op_tbl_t; |
48 | 48 | ||
49 | op_tbl_t op_table [] = { | 49 | op_tbl_t op_table [] = { |
50 | { "-lt", LT }, | 50 | { "-lt", LT }, |
51 | { "<" , LT }, | 51 | { "<" , LT }, |
52 | { "-gt", GT }, | 52 | { "-gt", GT }, |
53 | { ">" , GT }, | 53 | { ">" , GT }, |
54 | { "-eq", EQ }, | 54 | { "-eq", EQ }, |
55 | { "==" , EQ }, | 55 | { "==" , EQ }, |
56 | { "-ne", NE }, | 56 | { "-ne", NE }, |
57 | { "!=" , NE }, | 57 | { "!=" , NE }, |
58 | { "<>" , NE }, | 58 | { "<>" , NE }, |
59 | { "-ge", GE }, | 59 | { "-ge", GE }, |
60 | { ">=" , GE }, | 60 | { ">=" , GE }, |
61 | { "-le", LE }, | 61 | { "-le", LE }, |
62 | { "<=" , LE }, | 62 | { "<=" , LE }, |
63 | }; | 63 | }; |
64 | 64 | ||
65 | #define op_tbl_size (sizeof(op_table)/sizeof(op_table[0])) | 65 | #define op_tbl_size (sizeof(op_table)/sizeof(op_table[0])) |
66 | 66 | ||
67 | static long evalexp(char *s, int w) | 67 | static long evalexp(char *s, int w) |
68 | { | 68 | { |
69 | long l, *p; | 69 | long l = 0; |
70 | long *p; | ||
70 | 71 | ||
71 | /* if the parameter starts with a * then assume is a pointer to the value we want */ | 72 | /* if the parameter starts with a * then assume is a pointer to the value we want */ |
72 | if (s[0] == '*') { | 73 | if (s[0] == '*') { |
73 | p = (long *)simple_strtoul(&s[1], NULL, 16); | 74 | p = (long *)simple_strtoul(&s[1], NULL, 16); |
74 | l = *p; | 75 | switch (w) { |
76 | case 1: return((long)(*(unsigned char *)p)); | ||
77 | case 2: return((long)(*(unsigned short *)p)); | ||
78 | case 4: return(*p); | ||
79 | } | ||
75 | } else { | 80 | } else { |
76 | l = simple_strtoul(s, NULL, 16); | 81 | l = simple_strtoul(s, NULL, 16); |
77 | } | 82 | } |
78 | 83 | ||
79 | return (l & ((1 << (w * 8)) - 1)); | 84 | return (l & ((1 << (w * 8)) - 1)); |
80 | } | 85 | } |
81 | 86 | ||
82 | static char * evalstr(char *s) | 87 | static char * evalstr(char *s) |
83 | { | 88 | { |
84 | /* if the parameter starts with a * then assume a string pointer else its a literal */ | 89 | /* if the parameter starts with a * then assume a string pointer else its a literal */ |
85 | if (s[0] == '*') { | 90 | if (s[0] == '*') { |
86 | return (char *)simple_strtoul(&s[1], NULL, 16); | 91 | return (char *)simple_strtoul(&s[1], NULL, 16); |
87 | } else { | 92 | } else { |
88 | return s; | 93 | return s; |
89 | } | 94 | } |
90 | } | 95 | } |
91 | 96 | ||
92 | static int stringcomp(char *s, char *t, int op) | 97 | static int stringcomp(char *s, char *t, int op) |
93 | { | 98 | { |
94 | int n, p; | 99 | int n, p; |
95 | char *l, *r; | 100 | char *l, *r; |
96 | 101 | ||
97 | l = evalstr(s); | 102 | l = evalstr(s); |
98 | r = evalstr(t); | 103 | r = evalstr(t); |
99 | 104 | ||
100 | /* we'll do a compare based on the length of the shortest string */ | 105 | /* we'll do a compare based on the length of the shortest string */ |
101 | n = min(strlen(l), strlen(r)); | 106 | n = min(strlen(l), strlen(r)); |
102 | 107 | ||
103 | p = strncmp(l, r, n); | 108 | p = strncmp(l, r, n); |
104 | switch (op) { | 109 | switch (op) { |
105 | case EQ: return (p == 0); | 110 | case EQ: return (p == 0); |
106 | case NE: return (p != 0); | 111 | case NE: return (p != 0); |
107 | case LT: return (p < 0); | 112 | case LT: return (p < 0); |
108 | case GT: return (p > 0); | 113 | case GT: return (p > 0); |
109 | case LE: return (p <= 0); | 114 | case LE: return (p <= 0); |
110 | case GE: return (p >= 0); | 115 | case GE: return (p >= 0); |
111 | } | 116 | } |
112 | return (0); | 117 | return (0); |
113 | } | 118 | } |
114 | 119 | ||
115 | static int arithcomp (char *s, char *t, int op, int w) | 120 | static int arithcomp (char *s, char *t, int op, int w) |
116 | { | 121 | { |
117 | long l, r; | 122 | long l, r; |
118 | 123 | ||
119 | l = evalexp (s, w); | 124 | l = evalexp (s, w); |
120 | r = evalexp (t, w); | 125 | r = evalexp (t, w); |
121 | 126 | ||
122 | switch (op) { | 127 | switch (op) { |
123 | case EQ: return (l == r); | 128 | case EQ: return (l == r); |
124 | case NE: return (l != r); | 129 | case NE: return (l != r); |
125 | case LT: return (l < r); | 130 | case LT: return (l < r); |
126 | case GT: return (l > r); | 131 | case GT: return (l > r); |
127 | case LE: return (l <= r); | 132 | case LE: return (l <= r); |
128 | case GE: return (l >= r); | 133 | case GE: return (l >= r); |
129 | } | 134 | } |
130 | return (0); | 135 | return (0); |
131 | } | 136 | } |
132 | 137 | ||
133 | int binary_test (char *op, char *arg1, char *arg2, int w) | 138 | int binary_test (char *op, char *arg1, char *arg2, int w) |
134 | { | 139 | { |
135 | int len, i; | 140 | int len, i; |
136 | op_tbl_t *optp; | 141 | op_tbl_t *optp; |
137 | 142 | ||
138 | len = strlen(op); | 143 | len = strlen(op); |
139 | 144 | ||
140 | for (optp = (op_tbl_t *)&op_table, i = 0; | 145 | for (optp = (op_tbl_t *)&op_table, i = 0; |
141 | i < op_tbl_size; | 146 | i < op_tbl_size; |
142 | optp++, i++) { | 147 | optp++, i++) { |
143 | 148 | ||
144 | if ((strncmp (op, optp->op, len) == 0) && (len == strlen (optp->op))) { | 149 | if ((strncmp (op, optp->op, len) == 0) && (len == strlen (optp->op))) { |
145 | if (w == 0) { | 150 | if (w == 0) { |
146 | return (stringcomp(arg1, arg2, optp->opcode)); | 151 | return (stringcomp(arg1, arg2, optp->opcode)); |
147 | } else { | 152 | } else { |
148 | return (arithcomp (arg1, arg2, optp->opcode, w)); | 153 | return (arithcomp (arg1, arg2, optp->opcode, w)); |
149 | } | 154 | } |
150 | } | 155 | } |
151 | } | 156 | } |
152 | 157 | ||
153 | printf("Unknown operator '%s'\n", op); | 158 | printf("Unknown operator '%s'\n", op); |
154 | return 0; /* op code not found */ | 159 | return 0; /* op code not found */ |
155 | } | 160 | } |
156 | 161 | ||
157 | /* command line interface to the shell test */ | 162 | /* command line interface to the shell test */ |
158 | int do_itest ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] ) | 163 | int do_itest ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] ) |
159 | { | 164 | { |
160 | int value, w; | 165 | int value, w; |
161 | 166 | ||
162 | /* Validate arguments */ | 167 | /* Validate arguments */ |
163 | if ((argc != 4)){ | 168 | if ((argc != 4)){ |
164 | cmd_usage(cmdtp); | 169 | cmd_usage(cmdtp); |
165 | return 1; | 170 | return 1; |
166 | } | 171 | } |
167 | 172 | ||
168 | /* Check for a data width specification. | 173 | /* Check for a data width specification. |
169 | * Defaults to long (4) if no specification. | 174 | * Defaults to long (4) if no specification. |
170 | * Uses -2 as 'width' for .s (string) so as not to upset existing code | 175 | * Uses -2 as 'width' for .s (string) so as not to upset existing code |
171 | */ | 176 | */ |
172 | switch (w = cmd_get_data_size(argv[0], 4)) { | 177 | switch (w = cmd_get_data_size(argv[0], 4)) { |
173 | case 1: | 178 | case 1: |
174 | case 2: | 179 | case 2: |
175 | case 4: | 180 | case 4: |
176 | value = binary_test (argv[2], argv[1], argv[3], w); | 181 | value = binary_test (argv[2], argv[1], argv[3], w); |
177 | break; | 182 | break; |
178 | case -2: | 183 | case -2: |
179 | value = binary_test (argv[2], argv[1], argv[3], 0); | 184 | value = binary_test (argv[2], argv[1], argv[3], 0); |
180 | break; | 185 | break; |
181 | case -1: | 186 | case -1: |
182 | default: | 187 | default: |
183 | puts("Invalid data width specifier\n"); | 188 | puts("Invalid data width specifier\n"); |
184 | value = 0; | 189 | value = 0; |
185 | break; | 190 | break; |
186 | } | 191 | } |
187 | 192 | ||
188 | return !value; | 193 | return !value; |
189 | } | 194 | } |
190 | 195 | ||
191 | U_BOOT_CMD( | 196 | U_BOOT_CMD( |
192 | itest, 4, 0, do_itest, | 197 | itest, 4, 0, do_itest, |
193 | "return true/false on integer compare", | 198 | "return true/false on integer compare", |
194 | "[.b, .w, .l, .s] [*]value1 <op> [*]value2" | 199 | "[.b, .w, .l, .s] [*]value1 <op> [*]value2" |
195 | ); | 200 | ); |
196 | 201 |