@@ -15,14 +15,44 @@ var request = require('request')
15
15
, yaml = require ( 'yamlparser' ) ;
16
16
17
17
/**
18
- * Update the regexp.js file
18
+ * Local modules.
19
+ */
20
+ var old = require ( './regexps' ) ;
21
+
22
+ function getKnown ( old ) {
23
+ var known = new Set ( ) ;
24
+ for ( var type in old ) {
25
+ if ( ! old . hasOwnProperty ( type ) ) continue ;
26
+ var group = old [ type ] ;
27
+ for ( var i = 0 ; i < group . length ; i ++ ) {
28
+ var regex = group [ i ] [ 0 ] . source ;
29
+ known . add ( regex ) ;
30
+ }
31
+ }
32
+ return known ;
33
+ }
34
+
35
+ var known = getKnown ( old ) ;
36
+
37
+ function isSafe ( source ) {
38
+ if ( ! / [ + * { ] .* [ + * { ] / . test ( source ) ) return true ; // -35%
39
+ return false ;
40
+ }
41
+
42
+ /**
43
+ * Update the regexps.js file
19
44
*
20
- * @param {String } remote optional remote URL for regex source
45
+ * @param {String } [ remote] optional remote URL for regex source
21
46
* @param {Function } callback Completion callback.
22
47
* @api public
23
48
*/
24
- exports . update = function update ( remote , callback ) {
49
+ exports . update = function update ( ) {
50
+ let remote , callback ;
51
+
52
+ if ( arguments . length === 2 ) [ remote , callback ] = arguments ;
53
+ else if ( arguments . length === 1 ) [ callback ] = arguments ;
25
54
if ( remote !== undefined ) exports . remote = remote ;
55
+
26
56
// Prepend local additions that are missing from the source
27
57
fs . readFile ( exports . before , 'utf8' , function reading ( err , before ) {
28
58
if ( err ) return callback ( err ) ;
@@ -47,10 +77,8 @@ exports.update = function update(remote, callback) {
47
77
//
48
78
tmp . file ( function ( err , tempFilePath ) {
49
79
if ( err ) return ;
50
-
51
80
fs . writeFile ( tempFilePath , source , function idk ( err ) {
52
81
if ( err ) return
53
-
54
82
fs . rename ( tempFilePath , exports . output , function ( err ) {
55
83
56
84
} ) ;
@@ -70,6 +98,7 @@ exports.update = function update(remote, callback) {
70
98
* @api public
71
99
*/
72
100
exports . parse = function parse ( sources , callback ) {
101
+ var unsafe = [ ] ;
73
102
var results = { } ;
74
103
75
104
var data = sources . reduce ( function parser ( memo , data ) {
@@ -124,16 +153,29 @@ exports.parse = function parse(sources, callback) {
124
153
var resources = data [ details . resource ]
125
154
, name = details . resource . replace ( '_parsers' , '' )
126
155
, resource
156
+ , regex
157
+ , source
127
158
, parser ;
128
159
129
160
for ( var i = 0 , l = resources . length ; i < l ; i ++ ) {
130
161
resource = resources [ i ] ;
162
+ regex = resource . regex ;
163
+
164
+ source = new RegExp ( regex ) . source ;
165
+ if ( ! known . has ( source ) ) {
166
+ // A quick check, regexes not matching those are clearly safe
167
+ // This check excludes about 35% of all regexps we have
168
+ if ( ! isSafe ( source ) ) {
169
+ unsafe . push ( source ) ;
170
+ }
171
+ known . add ( source ) ;
172
+ }
131
173
132
174
// We need to JSON stringify the data to properly add slashes escape other
133
175
// kinds of crap in the RegularExpression. If we don't do thing we get
134
176
// some illegal token warnings.
135
177
parser = 'parser = Object.create(null);\n' ;
136
- parser += 'parser[0] = new RegExp(' + JSON . stringify ( resource . regex ) + ');\n' ;
178
+ parser += 'parser[0] = new RegExp(' + JSON . stringify ( regex ) + ');\n' ;
137
179
138
180
// Check if we have replacement for the parsed family name
139
181
if ( resource [ details . replacement ] ) {
@@ -172,6 +214,16 @@ exports.parse = function parse(sources, callback) {
172
214
}
173
215
} ) ;
174
216
217
+ if ( unsafe . length > 0 ) {
218
+ console . log ( 'There are new regexps! Here they are, one per line:' ) ;
219
+ for ( var i = 0 ; i < unsafe . length ; i ++ ) {
220
+ console . log ( ' ' + unsafe [ i ] ) ;
221
+ }
222
+ console . log ( 'Those might be potentially unsafe and cause ReDoS.' ) ;
223
+ console . log ( 'Make sure to take them through Weideman\'s tool and to inspect them!' ) ;
224
+ console . log ( 'See https://github.com/NicolaasWeideman/RegexStaticAnalysis' ) ;
225
+ }
226
+
175
227
// Generate a correct format
176
228
exports . generate ( results , callback ) ;
177
229
} ;
@@ -222,7 +274,7 @@ exports.generate = function generate(results, callback) {
222
274
* @type {String }
223
275
* @api private
224
276
*/
225
- exports . remote = 'https://raw.githubusercontent.com/ua-parser/uap-core/master/regexes.yaml' ;
277
+ exports . remote = process . env . USERAGENT_REMOTE ? process . env . USERAGENT_REMOTE : 'https://raw.githubusercontent.com/ua-parser/uap-core/master/regexes.yaml' ;
226
278
227
279
/**
228
280
* The locations of our local regexes yaml files.
0 commit comments