Просмотр исходного кода

block javascript property names being used as file names

Brian Gough 8 лет назад
Родитель
Сommit
8a10e98b56

+ 29 - 1
services/web/app/coffee/Features/Project/SafePath.coffee

@@ -23,6 +23,31 @@ load = () ->
 		| (\s+$)    # reject trailing space
 		| (\s+$)    # reject trailing space
 		///g
 		///g
 
 
+	# Put a block on filenames which match javascript property names, as they
+	# can cause exceptions where the code puts filenames into a hash. This is a
+	# temporary workaround until the code in other places is made safe against
+	# property names.
+	#
+	# The list of property names is taken from
+	#   ['prototype'].concat(Object.getOwnPropertyNames(Object.prototype))
+	BLOCKEDFILE_RX = ///
+		^(
+			prototype
+			|constructor
+			|toString
+			|toLocaleString
+			|valueOf
+			|hasOwnProperty
+			|isPrototypeOf
+			|propertyIsEnumerable
+			|__defineGetter__
+			|__lookupGetter__
+			|__defineSetter__
+			|__lookupSetter__
+			|__proto__
+		)$
+	///
+
 	MAX_PATH = 1024 # Maximum path length, in characters. This is fairly arbitrary.
 	MAX_PATH = 1024 # Maximum path length, in characters. This is fairly arbitrary.
 
 
 	SafePath =
 	SafePath =
@@ -31,12 +56,15 @@ load = () ->
 			# for BADFILE_RX replace any matches with an equal number of underscores
 			# for BADFILE_RX replace any matches with an equal number of underscores
 			filename = filename.replace BADFILE_RX, (match) -> 
 			filename = filename.replace BADFILE_RX, (match) -> 
 				return new Array(match.length + 1).join("_")
 				return new Array(match.length + 1).join("_")
+			# replace blocked filenames 'prototype' with '@prototype'
+			filename = filename.replace BLOCKEDFILE_RX, "@$1"
 			return filename
 			return filename
 
 
 		isCleanFilename: (filename) ->
 		isCleanFilename: (filename) ->
 			return SafePath.isAllowedLength(filename) &&
 			return SafePath.isAllowedLength(filename) &&
 				not filename.match(BADCHAR_RX) &&
 				not filename.match(BADCHAR_RX) &&
-				not filename.match(BADFILE_RX)
+				not filename.match(BADFILE_RX) &&
+				not filename.match(BLOCKEDFILE_RX)
 
 
 		isAllowedLength: (pathname) ->
 		isAllowedLength: (pathname) ->
 			return pathname.length > 0 && pathname.length <= MAX_PATH
 			return pathname.length > 0 && pathname.length <= MAX_PATH

+ 29 - 1
services/web/public/coffee/ide/directives/SafePath.coffee

@@ -23,6 +23,31 @@ load = () ->
 		| (\s+$)    # reject trailing space
 		| (\s+$)    # reject trailing space
 		///g
 		///g
 
 
+	# Put a block on filenames which match javascript property names, as they
+	# can cause exceptions where the code puts filenames into a hash. This is a
+	# temporary workaround until the code in other places is made safe against
+	# property names.
+	#
+	# The list of property names is taken from
+	#   ['prototype'].concat(Object.getOwnPropertyNames(Object.prototype))
+	BLOCKEDFILE_RX = ///
+		^(
+			prototype
+			|constructor
+			|toString
+			|toLocaleString
+			|valueOf
+			|hasOwnProperty
+			|isPrototypeOf
+			|propertyIsEnumerable
+			|__defineGetter__
+			|__lookupGetter__
+			|__defineSetter__
+			|__lookupSetter__
+			|__proto__
+		)$
+	///
+
 	MAX_PATH = 1024 # Maximum path length, in characters. This is fairly arbitrary.
 	MAX_PATH = 1024 # Maximum path length, in characters. This is fairly arbitrary.
 
 
 	SafePath =
 	SafePath =
@@ -31,12 +56,15 @@ load = () ->
 			# for BADFILE_RX replace any matches with an equal number of underscores
 			# for BADFILE_RX replace any matches with an equal number of underscores
 			filename = filename.replace BADFILE_RX, (match) -> 
 			filename = filename.replace BADFILE_RX, (match) -> 
 				return new Array(match.length + 1).join("_")
 				return new Array(match.length + 1).join("_")
+			# replace blocked filenames 'prototype' with '@prototype'
+			filename = filename.replace BLOCKEDFILE_RX, "@$1"
 			return filename
 			return filename
 
 
 		isCleanFilename: (filename) ->
 		isCleanFilename: (filename) ->
 			return SafePath.isAllowedLength(filename) &&
 			return SafePath.isAllowedLength(filename) &&
 				not filename.match(BADCHAR_RX) &&
 				not filename.match(BADCHAR_RX) &&
-				not filename.match(BADFILE_RX)
+				not filename.match(BADFILE_RX) &&
+				not filename.match(BLOCKEDFILE_RX)
 
 
 		isAllowedLength: (pathname) ->
 		isAllowedLength: (pathname) ->
 			return pathname.length > 0 && pathname.length <= MAX_PATH
 			return pathname.length > 0 && pathname.length <= MAX_PATH

+ 19 - 2
services/web/test/unit/coffee/Project/SafePathTests.coffee

@@ -63,7 +63,17 @@ describe 'SafePath', ->
 			result = @SafePath.isCleanFilename 'foo\uD800\uDFFFbar'
 			result = @SafePath.isCleanFilename 'foo\uD800\uDFFFbar'
 			result.should.equal false
 			result.should.equal false
 
 
+		it 'should not accept javascript property names', ->
+			result = @SafePath.isCleanFilename 'prototype'
+			result.should.equal false
 
 
+		it 'should not accept javascript property names in the prototype', ->
+			result = @SafePath.isCleanFilename 'hasOwnProperty'
+			result.should.equal false
+
+		it 'should not accept javascript property names resulting from substitutions', ->
+			result = @SafePath.isCleanFilename '  proto  '
+			result.should.equal false
 
 
 		# it 'should not accept a trailing .', ->
 		# it 'should not accept a trailing .', ->
 		# 	result = @SafePath.isCleanFilename 'hello.'
 		# 	result = @SafePath.isCleanFilename 'hello.'
@@ -119,5 +129,12 @@ describe 'SafePath', ->
 
 
 		it 'should replace a multiple leading spaces with ___', ->
 		it 'should replace a multiple leading spaces with ___', ->
 			result = @SafePath.clean '  foo'
 			result = @SafePath.clean '  foo'
-			result.should.equal '__foo'		
-
+			result.should.equal '__foo'
+
+		it 'should prefix javascript property names with @', ->
+			result = @SafePath.clean 'prototype'
+			result.should.equal '@prototype'
+		
+		it 'should prefix javascript property names in the prototype with @', ->
+			result = @SafePath.clean 'hasOwnProperty'
+			result.should.equal '@hasOwnProperty'