@@ -302,7 +302,7 @@ class ContextType(object):
302
302
>>> context.os == 'linux'
303
303
True
304
304
>>> context.arch = 'arm'
305
- >>> vars(context) == {'arch': 'arm', 'bits': 32, 'endian': 'little', 'os': 'linux'}
305
+ >>> vars(context) == {'arch': 'arm', 'bits': 32, 'endian': 'little', 'os': 'linux', 'newline': b'\n' }
306
306
True
307
307
>>> context.endian
308
308
'little'
@@ -376,8 +376,19 @@ class ContextType(object):
376
376
'timeout' : Timeout .maximum ,
377
377
}
378
378
379
- #: Valid values for :meth:`pwnlib.context.ContextType.os`
380
- oses = sorted (('linux' ,'freebsd' ,'windows' ,'cgc' ,'android' ,'baremetal' ,'darwin' ))
379
+ unix_like = {'newline' : b'\n ' }
380
+ windows_like = {'newline' : b'\r \n ' }
381
+
382
+ #: Keys are valid values for :meth:`pwnlib.context.ContextType.os`
383
+ oses = _longest ({
384
+ 'linux' : unix_like ,
385
+ 'freebsd' : unix_like ,
386
+ 'windows' : windows_like ,
387
+ 'cgc' : unix_like ,
388
+ 'android' : unix_like ,
389
+ 'baremetal' : unix_like ,
390
+ 'darwin' : unix_like ,
391
+ })
381
392
382
393
big_32 = {'endian' : 'big' , 'bits' : 32 }
383
394
big_64 = {'endian' : 'big' , 'bits' : 64 }
@@ -446,14 +457,14 @@ def __init__(self, **kwargs):
446
457
447
458
448
459
def copy (self ):
449
- """copy() -> dict
460
+ r """copy() -> dict
450
461
Returns a copy of the current context as a dictionary.
451
462
452
463
Examples:
453
464
454
465
>>> context.clear()
455
466
>>> context.os = 'linux'
456
- >>> vars(context) == {'os': 'linux'}
467
+ >>> vars(context) == {'os': 'linux', 'newline': b'\n' }
457
468
True
458
469
"""
459
470
return self ._tls .copy ()
@@ -1104,25 +1115,73 @@ def mask(self):
1104
1115
1105
1116
@_validator
1106
1117
def os (self , os ):
1107
- """
1118
+ r """
1108
1119
Operating system of the target machine.
1109
1120
1110
1121
The default value is ``linux``.
1111
1122
1112
1123
Allowed values are listed in :attr:`pwnlib.context.ContextType.oses`.
1113
1124
1125
+ Side Effects:
1126
+
1127
+ If an os is specified some attributes will be set on the context
1128
+ if a user has not already set a value.
1129
+
1130
+ The following property may be modified:
1131
+
1132
+ - :attr:`newline`
1133
+
1134
+ Raises:
1135
+ AttributeError: An invalid os was specified
1136
+
1114
1137
Examples:
1115
1138
1116
- >>> context.os = 'linux'
1139
+ >>> context.clear()
1140
+ >>> context.os == 'linux' # Default os
1141
+ True
1142
+
1143
+ >>> context.os = 'freebsd'
1144
+ >>> context.os == 'freebsd'
1145
+ True
1146
+
1117
1147
>>> context.os = 'foobar' #doctest: +ELLIPSIS
1118
1148
Traceback (most recent call last):
1119
1149
...
1120
1150
AttributeError: os must be one of ['android', 'baremetal', 'cgc', 'freebsd', 'linux', 'windows']
1151
+
1152
+ >>> context.clear()
1153
+ >>> context.newline == b'\n' # Default value
1154
+ True
1155
+ >>> context.os = 'windows'
1156
+ >>> context.newline == b'\r\n' # New value
1157
+ True
1158
+
1159
+ Note that expressly setting :attr:`newline` means that we use
1160
+ that value instead of the default
1161
+
1162
+ >>> context.clear()
1163
+ >>> context.newline = b'\n'
1164
+ >>> context.os = 'windows'
1165
+ >>> context.newline == b'\n'
1166
+ True
1167
+
1168
+ Setting the os can override the default for :attr:`newline`
1169
+
1170
+ >>> context.clear()
1171
+ >>> context.os = 'windows'
1172
+ >>> vars(context) == {'os': 'windows', 'newline': b'\r\n'}
1173
+ True
1121
1174
"""
1122
1175
os = os .lower ()
1123
1176
1124
- if os not in self .oses :
1125
- raise AttributeError ("os must be one of %r" % self .oses )
1177
+ try :
1178
+ defaults = self .oses [os ]
1179
+ except KeyError :
1180
+ raise AttributeError ("os must be one of %r" % sorted (self .oses ))
1181
+
1182
+ for k ,v in defaults .items ():
1183
+ if k not in self ._tls :
1184
+ self ._tls [k ] = v
1126
1185
1127
1186
return os
1128
1187
0 commit comments