Skip to content

Commit 12c5f39

Browse files
authored
Merge pull request #75 from MarcMil/develop
Fix support for EditText's InputTypes
2 parents da84b98 + 4e8c03c commit 12c5f39

File tree

3 files changed

+213
-16
lines changed

3 files changed

+213
-16
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package soot.jimple.infoflow.android.axml.flags;
2+
3+
import java.util.ArrayList;
4+
import java.util.Collection;
5+
import java.util.Iterator;
6+
import java.util.List;
7+
8+
/**
9+
* In some cases, bitmasks might be used in a way where there is a precendence of certain
10+
* masks to save space.
11+
* For "normal" bitmasks, the traditional way of checking is much faster.
12+
*
13+
* Simple Example:
14+
* Option A (can be used alone or in combination with others): 01
15+
* Option B (cannot be used with option A): 10
16+
* Option C (only valid when used with Option A): 11
17+
*
18+
* In this case, we could do checking of B via ((v & 10) == 1) && ((v & 1) != 1)
19+
* but sometimes there are a lot of options (e.g. inputType)
20+
*
21+
* @param <T> the keys used to distinguish flags
22+
*/
23+
public class BitwiseFlagSystem<T> {
24+
private List<T> keys = new ArrayList<T>();
25+
private List<Integer> values = new ArrayList<Integer>();
26+
27+
/**
28+
* Associate the given key with the bits set in set bits.
29+
* The first registration wins.
30+
* @param key the key
31+
* @param setBits the bits set
32+
*/
33+
public void register(T key, int setBits) {
34+
keys.add(key);
35+
values.add(setBits);
36+
}
37+
38+
/**
39+
* Returns all matching flags
40+
* @param inputValue input value
41+
*/
42+
public final Collection<T> getFlags(int value) {
43+
List<T> matchedResults = new ArrayList<>(4);
44+
List<Integer> matchedValues = new ArrayList<>(4);
45+
for (int i = 0; i < keys.size(); i++) {
46+
int v = values.get(i);
47+
if ((v & value) == v) {
48+
if (!hadAnyMatch(v, matchedValues)) {
49+
matchedResults.add(keys.get(i));
50+
matchedValues.add(v);
51+
}
52+
53+
}
54+
}
55+
return matchedResults;
56+
}
57+
58+
private static boolean hadAnyMatch(int value, List<Integer> matchedValues) {
59+
for (int c : matchedValues) {
60+
if ((c & value) == value) {
61+
return true;
62+
}
63+
}
64+
return false;
65+
}
66+
67+
/**
68+
* Checks whether all the given flags are set
69+
* @param inputValue input value
70+
* @param flag the flags to check
71+
*/
72+
@SafeVarargs
73+
public final boolean isSet(int inputValue, T... flag) {
74+
List<T> flagsLeft = new ArrayList<T>(flag.length);
75+
for (T i : flag)
76+
flagsLeft.add(i);
77+
78+
for (T t : getFlags(inputValue)) {
79+
Iterator<T> it = flagsLeft.iterator();
80+
while (it.hasNext()) {
81+
if (it.next().equals(t)) {
82+
it.remove();
83+
if (flagsLeft.isEmpty())
84+
return true;
85+
}
86+
}
87+
}
88+
return false;
89+
}
90+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package soot.jimple.infoflow.android.axml.flags;
2+
3+
import java.util.Collection;
4+
5+
/**
6+
* Support for EditText's input type
7+
*/
8+
public class InputType {
9+
private static final BitwiseFlagSystem<Integer> FLAG_SYSTEM = new BitwiseFlagSystem<>();
10+
public static int textFilter = 177;
11+
public static int textPostalAddress = 113;
12+
public static int textWebEmailAddress = 209;
13+
public static int textWebPassword = 225;
14+
public static int textEmailSubject = 49;
15+
public static int textLongMessage = 81;
16+
public static int textPersonName = 97;
17+
public static int textPhonetic = 193;
18+
public static int textVisiblePassword = 145;
19+
public static int textWebEditText = 161;
20+
public static int date = 20;
21+
public static int numberDecimal = 8194;
22+
public static int numberPassword = 225;
23+
public static int numberSigned = 4098;
24+
public static int phone = 3;
25+
public static int textAutoComplete = 65537;
26+
public static int textAutoCorrect = 32769;
27+
public static int textCapCharacters = 4097;
28+
public static int textCapWords = 8193;
29+
public static int textEmailAddress = 33;
30+
public static int textCapSentences = 16385;
31+
public static int textImeMultiLine = 262145;
32+
public static int textMultiLine = 131073;
33+
public static int textNoSuggestions = 524289;
34+
public static int textPassword = 129;
35+
public static int textShortMessage = 65;
36+
public static int textUri = 27;
37+
public static int time = 36;
38+
public static int datetime = 4;
39+
public static int number = 2;
40+
public static int text = 1;
41+
42+
static {
43+
//The order can be determined via the Android Framework and is highly relevant
44+
//See ResFlagsAttr.convertToResXmlFormat method to get the order
45+
FLAG_SYSTEM.register(textFilter, 177);
46+
FLAG_SYSTEM.register(textPostalAddress, 113);
47+
FLAG_SYSTEM.register(textWebEmailAddress, 209);
48+
FLAG_SYSTEM.register(textWebPassword, 225);
49+
FLAG_SYSTEM.register(textEmailSubject, 49);
50+
FLAG_SYSTEM.register(textLongMessage, 81);
51+
FLAG_SYSTEM.register(textPersonName, 97);
52+
FLAG_SYSTEM.register(textPhonetic, 193);
53+
FLAG_SYSTEM.register(textVisiblePassword, 145);
54+
FLAG_SYSTEM.register(textWebEditText, 161);
55+
FLAG_SYSTEM.register(date, 20);
56+
FLAG_SYSTEM.register(numberDecimal, 8194);
57+
FLAG_SYSTEM.register(numberPassword, 18);
58+
FLAG_SYSTEM.register(numberSigned, 4098);
59+
FLAG_SYSTEM.register(phone, 3);
60+
FLAG_SYSTEM.register(textAutoComplete, 65537);
61+
FLAG_SYSTEM.register(textAutoCorrect, 32769);
62+
FLAG_SYSTEM.register(textCapCharacters, 4097);
63+
FLAG_SYSTEM.register(textCapSentences, 16385);
64+
FLAG_SYSTEM.register(textCapWords, 8193);
65+
FLAG_SYSTEM.register(textEmailAddress, 33);
66+
FLAG_SYSTEM.register(textImeMultiLine, 262145);
67+
FLAG_SYSTEM.register(textMultiLine, 131073);
68+
FLAG_SYSTEM.register(textNoSuggestions, 524289);
69+
FLAG_SYSTEM.register(textPassword, 129);
70+
FLAG_SYSTEM.register(textShortMessage, 65);
71+
FLAG_SYSTEM.register(textUri, 17);
72+
FLAG_SYSTEM.register(time, 36);
73+
FLAG_SYSTEM.register(datetime, 4);
74+
FLAG_SYSTEM.register(number, 2);
75+
FLAG_SYSTEM.register(text, 1);
76+
}
77+
78+
/**
79+
* Checks whether all the given flags are set
80+
* @param inputValue input value
81+
* @param flag the flags to check
82+
*/
83+
public static boolean isSet(int inputValue, Integer... flag) {
84+
return FLAG_SYSTEM.isSet(inputValue, flag);
85+
}
86+
87+
/**
88+
* Returns all matching flags
89+
* @param inputValue input value
90+
*/
91+
public static Collection<Integer> getFlags(int inputValue) {
92+
return FLAG_SYSTEM.getFlags(inputValue);
93+
}
94+
}

soot-infoflow-android/src/soot/jimple/infoflow/android/resources/controls/EditTextControl.java

+29-16
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package soot.jimple.infoflow.android.resources.controls;
22

3+
import java.util.Collection;
34
import java.util.Collections;
45
import java.util.Map;
56

67
import pxb.android.axml.AxmlVisitor;
78
import soot.SootClass;
89
import soot.jimple.infoflow.android.axml.AXmlAttribute;
10+
import soot.jimple.infoflow.android.axml.flags.InputType;
911
import soot.jimple.infoflow.sourcesSinks.definitions.AccessPathTuple;
1012
import soot.jimple.infoflow.sourcesSinks.definitions.ISourceSinkCategory;
1113
import soot.jimple.infoflow.sourcesSinks.definitions.MethodSourceSinkDefinition;
@@ -20,14 +22,6 @@
2022
*
2123
*/
2224
public class EditTextControl extends AndroidLayoutControl {
23-
24-
public final static int TYPE_CLASS_TEXT = 0x00000001;
25-
public final static int TYPE_CLASS_NUMBER = 0x00000002;
26-
public final static int TYPE_NUMBER_VARIATION_PASSWORD = 0x00000010;
27-
public final static int TYPE_TEXT_VARIATION_PASSWORD = 0x00000080;
28-
public final static int TYPE_TEXT_VARIATION_VISIBLE_PASSWORD = 0x00000090;
29-
public final static int TYPE_TEXT_VARIATION_WEB_PASSWORD = 0x000000e0;
30-
3125
protected final static SourceSinkDefinition UI_PASSWORD_SOURCE_DEF;
3226
protected final static SourceSinkDefinition UI_ELEMENT_SOURCE_DEF;
3327

@@ -84,6 +78,7 @@ public String getID() {
8478
private int inputType;
8579
private boolean isPassword;
8680
private String text;
81+
private Collection<Integer> inputTypeFlags;
8782

8883
EditTextControl(SootClass viewClass) {
8984
super(viewClass);
@@ -105,6 +100,8 @@ public EditTextControl(int id, SootClass viewClass, Map<String, Object> addition
105100
*/
106101
void setInputType(int inputType) {
107102
this.inputType = inputType;
103+
this.inputTypeFlags = InputType.getFlags(inputType);
104+
108105
}
109106

110107
/**
@@ -116,6 +113,21 @@ public int getInputType() {
116113
return inputType;
117114
}
118115

116+
/**
117+
* Returns true if the input satiesfies all specified types
118+
* @see InputType
119+
* @param type the types to check
120+
*/
121+
public boolean satisfiesInputType(int... type) {
122+
if (inputTypeFlags == null)
123+
return false;
124+
125+
for (int i : type)
126+
if (!inputTypeFlags.contains(i))
127+
return false;
128+
return true;
129+
}
130+
119131
/**
120132
* Gets the text of this edit control
121133
*
@@ -131,7 +143,7 @@ protected void handleAttribute(AXmlAttribute<?> attribute, boolean loadOptionalD
131143
final int type = attribute.getType();
132144

133145
if (attrName.equals("inputType") && type == AxmlVisitor.TYPE_INT_HEX) {
134-
inputType = (Integer) attribute.getValue();
146+
setInputType((Integer) attribute.getValue());
135147
} else if (attrName.equals("password")) {
136148
if (type == AxmlVisitor.TYPE_INT_HEX)
137149
isPassword = ((Integer) attribute.getValue()) != 0; // -1 for
@@ -152,14 +164,15 @@ public boolean isSensitive() {
152164
if (isPassword)
153165
return true;
154166

155-
if ((inputType & TYPE_CLASS_NUMBER) == TYPE_CLASS_NUMBER)
156-
return ((inputType & TYPE_NUMBER_VARIATION_PASSWORD) == TYPE_NUMBER_VARIATION_PASSWORD);
167+
if (satisfiesInputType(InputType.numberPassword))
168+
return true;
169+
if (satisfiesInputType(InputType.textVisiblePassword))
170+
return true;
171+
if (satisfiesInputType(InputType.textWebPassword))
172+
return true;
173+
if (satisfiesInputType(InputType.textPassword))
174+
return true;
157175

158-
if ((inputType & TYPE_CLASS_TEXT) == TYPE_CLASS_TEXT) {
159-
return ((inputType & TYPE_TEXT_VARIATION_PASSWORD) == TYPE_TEXT_VARIATION_PASSWORD)
160-
|| ((inputType & TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) == TYPE_TEXT_VARIATION_VISIBLE_PASSWORD)
161-
|| ((inputType & TYPE_TEXT_VARIATION_WEB_PASSWORD) == TYPE_TEXT_VARIATION_WEB_PASSWORD);
162-
}
163176
return false;
164177
}
165178

0 commit comments

Comments
 (0)