Переглянути джерело

check for null bytes from JSON.stringify

Brian Gough 9 роки тому
батько
коміт
ab6fe1d948

+ 4 - 0
services/real-time/app/coffee/DocumentUpdaterManager.coffee

@@ -54,6 +54,10 @@ module.exports = DocumentUpdaterManager =
 				
 				
 	queueChange: (project_id, doc_id, change, callback = ()->)->
 	queueChange: (project_id, doc_id, change, callback = ()->)->
 		jsonChange = JSON.stringify change
 		jsonChange = JSON.stringify change
+		if jsonChange.indexOf("\u0000") != -1
+			error = new Error("null bytes found in op")
+			logger.error err: error, project_id: project_id, doc_id: doc_id, jsonChange: jsonChange, error.message
+			return callback(error)
 		doc_key = "#{project_id}:#{doc_id}"
 		doc_key = "#{project_id}:#{doc_id}"
 		# Push onto pendingUpdates for doc_id first, because once the doc updater
 		# Push onto pendingUpdates for doc_id first, because once the doc updater
 		# gets an entry on pending-updates-list, it starts processing.
 		# gets an entry on pending-updates-list, it starts processing.

+ 22 - 8
services/real-time/test/unit/coffee/DocumentUpdaterManagerTests.coffee

@@ -17,14 +17,17 @@ describe 'DocumentUpdaterManager', ->
 					pendingUpdates: ({doc_id}) -> "PendingUpdates:#{doc_id}"
 					pendingUpdates: ({doc_id}) -> "PendingUpdates:#{doc_id}"
 		@rclient = {auth:->}
 		@rclient = {auth:->}
 			
 			
-		@DocumentUpdaterManager = SandboxedModule.require modulePath, requires:
-			'settings-sharelatex':@settings
-			'logger-sharelatex': @logger = {log: sinon.stub(), error: sinon.stub(), warn: sinon.stub()}
-			'request': @request = {}
-			'redis-sharelatex' : createClient: () => @rclient
-			'metrics-sharelatex': @Metrics =
-				Timer: class Timer
-					done: () ->
+		@DocumentUpdaterManager = SandboxedModule.require modulePath,
+			requires:
+				'settings-sharelatex':@settings
+				'logger-sharelatex': @logger = {log: sinon.stub(), error: sinon.stub(), warn: sinon.stub()}
+				'request': @request = {}
+				'redis-sharelatex' : createClient: () => @rclient
+				'metrics-sharelatex': @Metrics =
+					Timer: class Timer
+						done: () ->
+			globals:
+				JSON: @JSON = Object.create(JSON) # avoid modifying JSON object directly
 
 
 	describe "getDocument", ->
 	describe "getDocument", ->
 		beforeEach ->
 		beforeEach ->
@@ -147,3 +150,14 @@ describe 'DocumentUpdaterManager', ->
 
 
 			it "should return an error", ->
 			it "should return an error", ->
 				@callback.calledWithExactly(sinon.match(Error)).should.equal true
 				@callback.calledWithExactly(sinon.match(Error)).should.equal true
+
+		describe "with null byte corruption", ->
+			beforeEach ->
+				@JSON.stringify = () -> return '["bad bytes! \u0000 <- here"]'
+				@DocumentUpdaterManager.queueChange(@project_id, @doc_id, @change, @callback)
+
+			it "should return an error", ->
+				@callback.calledWithExactly(sinon.match(Error)).should.equal true
+
+			it "should not push the change onto the pending-updates-list queue", ->
+				@rclient.rpush.called.should.equal false