Removed stale version of fuzzer; it's now internal.
BUG= Review URL: https://webrtc-codereview.appspot.com/971015 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3225 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@@ -1,20 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
|
||||||
#
|
|
||||||
# Use of this source code is governed by a BSD-style license
|
|
||||||
# that can be found in the LICENSE file in the root of the source
|
|
||||||
# tree. An additional intellectual property rights grant can be found
|
|
||||||
# in the file PATENTS. All contributing project authors may
|
|
||||||
# be found in the AUTHORS file in the root of the source tree.
|
|
||||||
|
|
||||||
|
|
||||||
class MissingParameterException(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def FillInParameter(parameter, value, template):
|
|
||||||
if parameter not in template:
|
|
||||||
raise MissingParameterException('Did not find parameter %s in template.' %
|
|
||||||
parameter)
|
|
||||||
|
|
||||||
return template.replace(parameter, value)
|
|
@@ -1,77 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
|
||||||
#
|
|
||||||
# Use of this source code is governed by a BSD-style license
|
|
||||||
# that can be found in the LICENSE file in the root of the source
|
|
||||||
# tree. An additional intellectual property rights grant can be found
|
|
||||||
# in the file PATENTS. All contributing project authors may
|
|
||||||
# be found in the AUTHORS file in the root of the source tree.
|
|
||||||
|
|
||||||
import random
|
|
||||||
import string
|
|
||||||
|
|
||||||
|
|
||||||
def RandomIdentifier():
|
|
||||||
"""Generates a random javascript identifier.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
A javascript identifier, which must start with a letter, continued by
|
|
||||||
letters and digits.
|
|
||||||
"""
|
|
||||||
length = random.randint(1, 25)
|
|
||||||
return (random.choice(string.letters) +
|
|
||||||
''.join(random.choice(string.letters + string.digits)
|
|
||||||
for i in xrange(length)))
|
|
||||||
|
|
||||||
|
|
||||||
def RandomJavascriptAttributes(num_attributes):
|
|
||||||
"""Generates a random set of attributes for javascript object.
|
|
||||||
|
|
||||||
Use like this, for instance:
|
|
||||||
my_object = 'var myObject = { %s };' % GenerateRandomJavascriptAttributes(5)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
A list of attribute strings.
|
|
||||||
"""
|
|
||||||
return ['%s: %s' % (RandomIdentifier(), RandomJavascriptValue())
|
|
||||||
for i in xrange(num_attributes)]
|
|
||||||
|
|
||||||
|
|
||||||
def MakeJavascriptObject(attributes):
|
|
||||||
"""Generates a javascript object from the provided list of attributes.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
attributes: A list of attribute strings.
|
|
||||||
Returns:
|
|
||||||
javascript code for the object.
|
|
||||||
"""
|
|
||||||
return '{ ' + ', '.join(attributes) + ' }'
|
|
||||||
|
|
||||||
|
|
||||||
def RandomJavascriptFunction():
|
|
||||||
"""Generates code for an empty javascript function with random arguments.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
javascript code for the function.
|
|
||||||
"""
|
|
||||||
num_parameters = random.randint(0, 10)
|
|
||||||
parameter_list = ', '.join(RandomIdentifier() for i in xrange(num_parameters))
|
|
||||||
return 'function ' + RandomIdentifier() + '(' + parameter_list + ')' + '{ }'
|
|
||||||
|
|
||||||
|
|
||||||
def RandomJavascriptValue():
|
|
||||||
"""Generates code for a random javascript expression.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Code for a javascript expression.
|
|
||||||
"""
|
|
||||||
roll = random.random()
|
|
||||||
if roll < 0.3:
|
|
||||||
return '"' + RandomIdentifier() + '"'
|
|
||||||
elif roll < 0.6:
|
|
||||||
return str(random.randint(-10000000, 10000000))
|
|
||||||
elif roll < 0.9:
|
|
||||||
# Functions are first-class objects.
|
|
||||||
return RandomJavascriptFunction()
|
|
||||||
else:
|
|
||||||
return 'true' if random.random() < 0.5 else 'false'
|
|
@@ -1 +0,0 @@
|
|||||||
../common/
|
|
@@ -1,45 +0,0 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
|
||||||
<!--
|
|
||||||
Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
|
||||||
|
|
||||||
Use of this source code is governed by a BSD-style license
|
|
||||||
that can be found in the LICENSE file in the root of the source
|
|
||||||
tree. An additional intellectual property rights grant can be found
|
|
||||||
in the file PATENTS. All contributing project authors may
|
|
||||||
be found in the AUTHORS file in the root of the source tree.
|
|
||||||
-->
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>WebRTC Fuzz Test Template</title>
|
|
||||||
<script type="text/javascript">
|
|
||||||
function requestVideo() {
|
|
||||||
BEFORE_GET_USER_MEDIA_CALL
|
|
||||||
navigator.webkitGetUserMedia(FUZZ_USER_MEDIA_INPUT,
|
|
||||||
FUZZ_OK_CALLBACK,
|
|
||||||
FUZZ_FAIL_CALLBACK);
|
|
||||||
AFTER_GET_USER_MEDIA_CALL
|
|
||||||
}
|
|
||||||
|
|
||||||
function getUserMediaFailedCallback(error) {
|
|
||||||
console.log('GetUserMedia call failed with code ' + error.code);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getUserMediaOkCallback(stream) {
|
|
||||||
var streamUrl = webkitURL.createObjectURL(stream);
|
|
||||||
document.getElementById('view1').src = streamUrl;
|
|
||||||
stream.stop()
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body onload="requestVideo();">
|
|
||||||
<table border="0">
|
|
||||||
<tr>
|
|
||||||
<td>Local Preview</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><video width="320" height="240" id="view1"
|
|
||||||
autoplay="autoplay"></video></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@@ -1,58 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
|
||||||
#
|
|
||||||
# Use of this source code is governed by a BSD-style license
|
|
||||||
# that can be found in the LICENSE file in the root of the source
|
|
||||||
# tree. An additional intellectual property rights grant can be found
|
|
||||||
# in the file PATENTS. All contributing project authors may
|
|
||||||
# be found in the AUTHORS file in the root of the source tree.
|
|
||||||
|
|
||||||
# Based on the ClusterFuzz simple fuzzer template.
|
|
||||||
|
|
||||||
import getopt
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import tempfile
|
|
||||||
import time
|
|
||||||
|
|
||||||
import get_user_media_fuzz
|
|
||||||
|
|
||||||
|
|
||||||
def GenerateData(input_dir):
|
|
||||||
template = open(os.path.join(input_dir, 'template.html'))
|
|
||||||
file_data = template.read()
|
|
||||||
template.close()
|
|
||||||
file_extension = 'html'
|
|
||||||
|
|
||||||
file_data = get_user_media_fuzz.Fuzz(file_data)
|
|
||||||
|
|
||||||
return file_data, file_extension
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
start_time = time.time()
|
|
||||||
|
|
||||||
no_of_files = None
|
|
||||||
input_dir = None
|
|
||||||
output_dir = None
|
|
||||||
optlist, args = getopt.getopt(sys.argv[1:], '', \
|
|
||||||
['no_of_files=', 'output_dir=', 'input_dir='])
|
|
||||||
for option, value in optlist:
|
|
||||||
if option == '--no_of_files': no_of_files = int(value)
|
|
||||||
elif option == '--output_dir': output_dir = value
|
|
||||||
elif option == '--input_dir': input_dir = value
|
|
||||||
assert no_of_files is not None, 'Missing "--no_of_files" argument'
|
|
||||||
assert output_dir is not None, 'Missing "--output_dir" argument'
|
|
||||||
assert input_dir is not None, 'Missing "--input_dir" argument'
|
|
||||||
|
|
||||||
for file_no in range(no_of_files):
|
|
||||||
file_data, file_extension = GenerateData(input_dir)
|
|
||||||
file_descriptor, file_path = tempfile.mkstemp(
|
|
||||||
prefix='fuzz-%d-%d' % (start_time, file_no),
|
|
||||||
suffix='.' + file_extension,
|
|
||||||
dir=output_dir)
|
|
||||||
file = os.fdopen(file_descriptor, 'wb')
|
|
||||||
print 'Writing %d bytes to "%s"' % (len(file_data), file_path)
|
|
||||||
print file_data
|
|
||||||
file.write(file_data)
|
|
||||||
file.close()
|
|
@@ -1,53 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
|
||||||
#
|
|
||||||
# Use of this source code is governed by a BSD-style license
|
|
||||||
# that can be found in the LICENSE file in the root of the source
|
|
||||||
# tree. An additional intellectual property rights grant can be found
|
|
||||||
# in the file PATENTS. All contributing project authors may
|
|
||||||
# be found in the AUTHORS file in the root of the source tree.
|
|
||||||
|
|
||||||
import random
|
|
||||||
|
|
||||||
from common.fuzz_parameters import FillInParameter
|
|
||||||
from common.random_javascript import *
|
|
||||||
|
|
||||||
def Fuzz(template):
|
|
||||||
"""Generates a single random HTML page which tries to mess with getUserMedia.
|
|
||||||
|
|
||||||
We require a template which has certain placeholders defined in it (such
|
|
||||||
as FUZZ_USER_MEDIA_INPUT). We then replace these placeholders with random
|
|
||||||
identifiers and data in certain patterns. For instance, since the getUserMedia
|
|
||||||
function accepts an object, we try to pass in everything from {video:true,
|
|
||||||
audio:false} (which is a correct value) to {sdjkjsjh34sd:455, video:'yxuhsd'}
|
|
||||||
and other strange things.
|
|
||||||
|
|
||||||
See the template at corpus/template.html for an example of how a template
|
|
||||||
looks like.
|
|
||||||
"""
|
|
||||||
random.seed()
|
|
||||||
attributes = RandomJavascriptAttributes(random.randint(0, 10))
|
|
||||||
if (random.random() < 0.8):
|
|
||||||
attributes.append('video: %s' % RandomJavascriptValue())
|
|
||||||
if (random.random() < 0.8):
|
|
||||||
attributes.append('audio: %s' % RandomJavascriptValue())
|
|
||||||
input_object = MakeJavascriptObject(attributes)
|
|
||||||
template = FillInParameter('FUZZ_USER_MEDIA_INPUT', input_object, template)
|
|
||||||
|
|
||||||
ok_callback = (RandomJavascriptValue()
|
|
||||||
if random.random() < 0.5 else 'getUserMediaOkCallback')
|
|
||||||
template = FillInParameter('FUZZ_OK_CALLBACK', ok_callback, template)
|
|
||||||
|
|
||||||
fail_callback = (RandomJavascriptValue()
|
|
||||||
if random.random() < 0.5 else 'getUserMediaFailedCallback')
|
|
||||||
template = FillInParameter('FUZZ_FAIL_CALLBACK', fail_callback, template)
|
|
||||||
|
|
||||||
before_call = 'location.reload();' if random.random() < 0.1 else ''
|
|
||||||
template = FillInParameter('BEFORE_GET_USER_MEDIA_CALL', before_call,
|
|
||||||
template)
|
|
||||||
|
|
||||||
after_call = 'location.reload();' if random.random() < 0.3 else ''
|
|
||||||
template = FillInParameter('AFTER_GET_USER_MEDIA_CALL', after_call,
|
|
||||||
template)
|
|
||||||
|
|
||||||
return template
|
|
@@ -1 +0,0 @@
|
|||||||
../common/
|
|
@@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license
|
|
||||||
* that can be found in the LICENSE file in the root of the source
|
|
||||||
* tree. An additional intellectual property rights grant can be found
|
|
||||||
* in the file PATENTS. All contributing project authors may
|
|
||||||
* be found in the AUTHORS file in the root of the source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function fuzzSdp(originalSdp) {
|
|
||||||
var lines = originalSdp.split('\n');
|
|
||||||
shuffle(lines);
|
|
||||||
return lines.join('\n');
|
|
||||||
}
|
|
@@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license
|
|
||||||
* that can be found in the LICENSE file in the root of the source
|
|
||||||
* tree. An additional intellectual property rights grant can be found
|
|
||||||
* in the file PATENTS. All contributing project authors may
|
|
||||||
* be found in the AUTHORS file in the root of the source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @private */
|
|
||||||
var gRandomRolls = null;
|
|
||||||
/** @private */
|
|
||||||
var gCurrentRoll = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gives us a bunch of random numbers [0, 1] we can use to make random choices.
|
|
||||||
* This function is here since we want the fuzzer to be able to write the
|
|
||||||
* random choices into the file for later reproduction. This would have been
|
|
||||||
* easier if there was a seedable random generator in javascript, but in that
|
|
||||||
* case we would have to write it ourselves.
|
|
||||||
*
|
|
||||||
* @param randomRolls An array of floating-point numbers [0, 1].
|
|
||||||
*/
|
|
||||||
function setRandomRolls(randomRolls) {
|
|
||||||
gRandomRolls = randomRolls;
|
|
||||||
gCurrentRoll = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shuffles the provided array. We will run n swaps, where 0 <= n <= length.
|
|
||||||
* n is randomly chosen within those constraints.
|
|
||||||
*
|
|
||||||
* @param array The array (shuffled in-place).
|
|
||||||
*/
|
|
||||||
function shuffle(array) {
|
|
||||||
var numToSwap = Math.floor(random_() * array.length);
|
|
||||||
var numSwapped = 0;
|
|
||||||
|
|
||||||
// Run a Fisher-Yates shuffle but randomly limit the number of lines we
|
|
||||||
// swap (see http://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
|
|
||||||
for (i = array.length - 1; numSwapped < numToSwap; i--) {
|
|
||||||
var j = Math.floor(random_() * i);
|
|
||||||
var tmp = array[i];
|
|
||||||
array[i] = array[j];
|
|
||||||
array[j] = tmp;
|
|
||||||
numSwapped = array.length - i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @private */
|
|
||||||
function random_() {
|
|
||||||
if (gRandomRolls == null)
|
|
||||||
throw "setRandomRolls has not been called!";
|
|
||||||
if (gCurrentRoll >= gRandomRolls.length)
|
|
||||||
throw "ran out of random rolls after " + gCurrentRoll + " rolls.";
|
|
||||||
return gRandomRolls[gCurrentRoll++];
|
|
||||||
}
|
|
@@ -1,126 +0,0 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
|
||||||
<!--
|
|
||||||
Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
|
||||||
|
|
||||||
Use of this source code is governed by a BSD-style license
|
|
||||||
that can be found in the LICENSE file in the root of the source
|
|
||||||
tree. An additional intellectual property rights grant can be found
|
|
||||||
in the file PATENTS. All contributing project authors may
|
|
||||||
be found in the AUTHORS file in the root of the source tree.
|
|
||||||
-->
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>WebRTC PeerConnection Fuzz Test Template</title>
|
|
||||||
INCLUDE_RANDOM_JS
|
|
||||||
INCLUDE_FUZZ_SDP_JS
|
|
||||||
<script type="text/javascript">
|
|
||||||
var gFirstConnection = null;
|
|
||||||
var gSecondConnection = null;
|
|
||||||
|
|
||||||
// Variables in caps are filled in by the fuzzer.
|
|
||||||
var gTransformOfferSdp = TRANSFORM_OFFER_SDP;
|
|
||||||
var gTransformAnswerSdp = TRANSFORM_ANSWER_SDP;
|
|
||||||
|
|
||||||
// START_OF_POSSIBLE_INJECTED_LOCATION_RELOADS
|
|
||||||
function startTest() {
|
|
||||||
navigator.webkitGetUserMedia(REQUEST_AUDIO_AND_VIDEO,
|
|
||||||
getUserMediaOkCallback,
|
|
||||||
getUserMediaFailedCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getUserMediaFailedCallback(error) {
|
|
||||||
console.log('getUserMedia request failed with code ' + error.code);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getUserMediaOkCallback(localStream) {
|
|
||||||
var localStreamUrl = webkitURL.createObjectURL(localStream);
|
|
||||||
document.getElementById('local-view').src = localStreamUrl;
|
|
||||||
|
|
||||||
callUsingStream(localStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
function callUsingStream(localStream) {
|
|
||||||
gFirstConnection = new webkitRTCPeerConnection(null, null);
|
|
||||||
gFirstConnection.onicecandidate = onIceCandidateToFirst;
|
|
||||||
gFirstConnection.addStream(localStream);
|
|
||||||
gFirstConnection.createOffer(onOfferCreated);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onOfferCreated(offer) {
|
|
||||||
gFirstConnection.setLocalDescription(offer);
|
|
||||||
|
|
||||||
var offerSdp = gTransformOfferSdp(offer.sdp);
|
|
||||||
console.log('OFFER SDP MESSAGE:' + offerSdp);
|
|
||||||
receiveCall(offerSdp);
|
|
||||||
}
|
|
||||||
|
|
||||||
function receiveCall(offerSdp) {
|
|
||||||
gSecondConnection = new webkitRTCPeerConnection(null, null);
|
|
||||||
gSecondConnection.onicecandidate = onIceCandidateToSecond;
|
|
||||||
gSecondConnection.onaddstream = onRemoteStream;
|
|
||||||
|
|
||||||
var parsedOffer = new RTCSessionDescription({ type: 'offer',
|
|
||||||
sdp: offerSdp });
|
|
||||||
gSecondConnection.setRemoteDescription(parsedOffer);
|
|
||||||
|
|
||||||
gSecondConnection.createAnswer(onAnswerCreated);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onAnswerCreated(answer) {
|
|
||||||
gSecondConnection.setLocalDescription(answer);
|
|
||||||
|
|
||||||
answerSdp = gTransformAnswerSdp(answer.sdp);
|
|
||||||
console.log('ANSWER SDP MESSAGE:' + answerSdp);
|
|
||||||
handleAnswer(answerSdp);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleAnswer(answerSdp) {
|
|
||||||
var parsedAnswer = new RTCSessionDescription({ type: 'answer',
|
|
||||||
sdp: answerSdp });
|
|
||||||
gFirstConnection.setRemoteDescription(parsedAnswer);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onIceCandidateToFirst(event) {
|
|
||||||
if (event.candidate) {
|
|
||||||
var candidate = new RTCIceCandidate(event.candidate);
|
|
||||||
gSecondConnection.addIceCandidate(candidate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onIceCandidateToSecond(event) {
|
|
||||||
if (event.candidate) {
|
|
||||||
var candidate = new RTCIceCandidate(event.candidate);
|
|
||||||
gFirstConnection.addIceCandidate(candidate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onRemoteStream(e) {
|
|
||||||
var remoteStreamUrl = webkitURL.createObjectURL(e.stream);
|
|
||||||
document.getElementById('remote-view').src = remoteStreamUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
window.onload = function() {
|
|
||||||
setRandomRolls(gRandomRolls);
|
|
||||||
startTest();
|
|
||||||
}
|
|
||||||
// END_OF_POSSIBLE_INJECTED_LOCATION_RELOADS
|
|
||||||
|
|
||||||
// This variable is placed here since its value is pretty big.
|
|
||||||
var gRandomRolls = ARRAY_OF_RANDOM_ROLLS;
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<table border="0">
|
|
||||||
<tr>
|
|
||||||
<td>Local Preview</td>
|
|
||||||
<td>Remote Stream</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><video width="320" height="240" id="local-view"
|
|
||||||
autoplay="autoplay"></video></td>
|
|
||||||
<td><video width="320" height="240" id="remote-view"
|
|
||||||
autoplay="autoplay"></video></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@@ -1,124 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
|
||||||
#
|
|
||||||
# Use of this source code is governed by a BSD-style license
|
|
||||||
# that can be found in the LICENSE file in the root of the source
|
|
||||||
# tree. An additional intellectual property rights grant can be found
|
|
||||||
# in the file PATENTS. All contributing project authors may
|
|
||||||
# be found in the AUTHORS file in the root of the source tree.
|
|
||||||
|
|
||||||
"""Fuzzer for peerconnection.
|
|
||||||
|
|
||||||
Based on the ClusterFuzz simple fuzzer template.
|
|
||||||
|
|
||||||
I generally use it like this when developing:
|
|
||||||
|
|
||||||
./src/test/fuzz/peerconnection/fuzz_main_run.py --no_of_files=1 \
|
|
||||||
--output_dir=. --input_dir=src/test/fuzz/peerconnection/corpus/; \
|
|
||||||
cat fuzz-*; mv fuzz-* /home/phoglund/www/fuzz/fuzz.html; \
|
|
||||||
cp src/test/fuzz/peerconnection/corpus/* /home/phoglund/www/fuzz/; \
|
|
||||||
chmod a+r /home/phoglund/www/fuzz/
|
|
||||||
|
|
||||||
Add the --be_nice flag to the fuzzer to generate a page that should be able
|
|
||||||
to set up a call. If a --be_nice-generated page doesn't get a call up, the
|
|
||||||
code doesn't work with whatever version of the WebRTC spec your current version
|
|
||||||
of Chrome implements.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import getopt
|
|
||||||
import os
|
|
||||||
import random
|
|
||||||
import sys
|
|
||||||
import tempfile
|
|
||||||
import time
|
|
||||||
|
|
||||||
from common.fuzz_parameters import FillInParameter
|
|
||||||
import peerconnection_fuzz
|
|
||||||
|
|
||||||
# TODO(phoglund): remove duplication wrt getusermedia once this code stabilizes.
|
|
||||||
|
|
||||||
|
|
||||||
def _ReadFile(path):
|
|
||||||
file_handle = open(path)
|
|
||||||
file_data = file_handle.read()
|
|
||||||
file_handle.close()
|
|
||||||
return file_data
|
|
||||||
|
|
||||||
|
|
||||||
def _Indent(file_data, num_spaces):
|
|
||||||
spaces = ' ' * num_spaces
|
|
||||||
return spaces + file_data.replace('\n', '\n' + spaces)
|
|
||||||
|
|
||||||
|
|
||||||
def _IncludeJsFile(js_include_to_replace, js_path, file_data):
|
|
||||||
js_file_data = _ReadFile(js_path)
|
|
||||||
js_file_data = _Indent(js_file_data, 4)
|
|
||||||
js_file_data = (' <script type="text/javascript">\n' +
|
|
||||||
js_file_data + '\n </script>\n')
|
|
||||||
return FillInParameter(js_include_to_replace, js_file_data, file_data)
|
|
||||||
|
|
||||||
|
|
||||||
def GenerateData(be_nice):
|
|
||||||
"""Generates a html page from the template, with or without fuzzing.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
be_nice: If true, we won't fuzz the data but rather produce a complete
|
|
||||||
standard-compliant file.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
A tuple (file_data, file_extension).
|
|
||||||
"""
|
|
||||||
this_scripts_path = os.path.dirname(os.path.realpath(__file__))
|
|
||||||
corpus_path = os.path.join(this_scripts_path, 'corpus');
|
|
||||||
|
|
||||||
template_to_use = 'template01.html'
|
|
||||||
template = _ReadFile(os.path.join(corpus_path, template_to_use))
|
|
||||||
|
|
||||||
file_extension = 'html'
|
|
||||||
|
|
||||||
if be_nice:
|
|
||||||
file_data = peerconnection_fuzz.MakeWorkingFile(template)
|
|
||||||
else:
|
|
||||||
file_data = peerconnection_fuzz.Fuzz(template)
|
|
||||||
|
|
||||||
# Paste the javascript code in directly since it's hard to make javascript
|
|
||||||
# includes work without data bundles.
|
|
||||||
file_data = _IncludeJsFile('INCLUDE_RANDOM_JS',
|
|
||||||
os.path.join(corpus_path, 'random.js'),
|
|
||||||
file_data)
|
|
||||||
file_data = _IncludeJsFile('INCLUDE_FUZZ_SDP_JS',
|
|
||||||
os.path.join(corpus_path, 'fuzz_sdp.js'),
|
|
||||||
file_data)
|
|
||||||
|
|
||||||
return file_data, file_extension
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
start_time = time.time()
|
|
||||||
|
|
||||||
no_of_files = None
|
|
||||||
input_dir = None
|
|
||||||
output_dir = None
|
|
||||||
be_nice = False
|
|
||||||
optlist, args = getopt.getopt(sys.argv[1:], '', \
|
|
||||||
['no_of_files=', 'output_dir=', 'input_dir=', 'be_nice'])
|
|
||||||
for option, value in optlist:
|
|
||||||
if option == '--no_of_files': no_of_files = int(value)
|
|
||||||
elif option == '--output_dir': output_dir = value
|
|
||||||
elif option == '--input_dir': input_dir = value
|
|
||||||
elif option == '--be_nice': be_nice = True
|
|
||||||
assert no_of_files is not None, 'Missing "--no_of_files" argument'
|
|
||||||
assert output_dir is not None, 'Missing "--output_dir" argument'
|
|
||||||
assert input_dir is not None, 'Missing "--input_dir" argument'
|
|
||||||
|
|
||||||
for file_no in range(no_of_files):
|
|
||||||
file_data, file_extension = GenerateData(be_nice)
|
|
||||||
file_data = file_data.encode('utf-8')
|
|
||||||
file_descriptor, file_path = tempfile.mkstemp(
|
|
||||||
prefix='fuzz-http-%d-%d' % (start_time, file_no),
|
|
||||||
suffix='.' + file_extension,
|
|
||||||
dir=output_dir)
|
|
||||||
file = os.fdopen(file_descriptor, 'wb')
|
|
||||||
print 'Writing %d bytes to "%s"' % (len(file_data), file_path)
|
|
||||||
file.write(file_data)
|
|
||||||
file.close()
|
|
@@ -1,170 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
|
||||||
#
|
|
||||||
# Use of this source code is governed by a BSD-style license
|
|
||||||
# that can be found in the LICENSE file in the root of the source
|
|
||||||
# tree. An additional intellectual property rights grant can be found
|
|
||||||
# in the file PATENTS. All contributing project authors may
|
|
||||||
# be found in the AUTHORS file in the root of the source tree.
|
|
||||||
|
|
||||||
import random
|
|
||||||
import re
|
|
||||||
import string
|
|
||||||
import unicodedata
|
|
||||||
|
|
||||||
from common.fuzz_parameters import FillInParameter, MissingParameterException
|
|
||||||
from common.random_javascript import *
|
|
||||||
|
|
||||||
|
|
||||||
def _ArrayOfRandomRolls(num_rolls):
|
|
||||||
return str([random.random() for x in xrange(num_rolls)])
|
|
||||||
|
|
||||||
|
|
||||||
def _RandomAudioOrVideo():
|
|
||||||
roll = random.random()
|
|
||||||
if roll < 0.5:
|
|
||||||
return '{ video: true, audio:true }'
|
|
||||||
elif roll < 0.7:
|
|
||||||
return '{ video: true, audio: false }'
|
|
||||||
elif roll < 0.9:
|
|
||||||
return '{ video: false, audio: true }'
|
|
||||||
else:
|
|
||||||
return '{ video: false, audio: true }'
|
|
||||||
|
|
||||||
|
|
||||||
def _ReturnFirstArgument():
|
|
||||||
return 'function(arg) { return arg; }'
|
|
||||||
|
|
||||||
|
|
||||||
def _ReturnRandomUtf8String():
|
|
||||||
unicode_glyphs = ''.join(unichr(char) for char in xrange(0x10ffff + 1)
|
|
||||||
if unicodedata.category(unichr(char))[0] in ('LMNPSZ'))
|
|
||||||
oh_dear = random.sample(unicode_glyphs, random.randint(50, 1500))
|
|
||||||
return 'function(arg) { return "%s"; }' % ''.join(oh_dear)
|
|
||||||
|
|
||||||
|
|
||||||
def _ReturnFuzzedSdp():
|
|
||||||
return 'function(arg) { return fuzzSdp(arg); }'
|
|
||||||
|
|
||||||
|
|
||||||
def _RandomSdpTransform():
|
|
||||||
roll = random.random()
|
|
||||||
if roll < 0.1:
|
|
||||||
return _ReturnRandomUtf8String()
|
|
||||||
elif roll < 0.5:
|
|
||||||
return _ReturnFuzzedSdp()
|
|
||||||
else:
|
|
||||||
return _ReturnFirstArgument()
|
|
||||||
|
|
||||||
|
|
||||||
def _InsertRandomLocationReload(list_of_lines, num_to_insert):
|
|
||||||
length = len(list_of_lines)
|
|
||||||
assert length > num_to_insert
|
|
||||||
|
|
||||||
# Randomly choose insertion points to insert at (if
|
|
||||||
# num_to_insert == length - 1, all will be replaced).
|
|
||||||
lines_to_insert_behind = sorted(random.sample(xrange(length - 1),
|
|
||||||
num_to_insert))
|
|
||||||
|
|
||||||
result = list(list_of_lines)
|
|
||||||
num_inserted = 0
|
|
||||||
for i in lines_to_insert_behind:
|
|
||||||
# We're just guessing the indentation the reloads will be at, but that's
|
|
||||||
# just cosmetic anyway.
|
|
||||||
result.insert(num_inserted + i + 1, ' location.reload()')
|
|
||||||
num_inserted += 1
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def _InsertRandomLocationReloads(file_data, replace_all):
|
|
||||||
lines = file_data.split(';\n')
|
|
||||||
if replace_all:
|
|
||||||
lines = _InsertRandomLocationReload(lines, len(lines) - 1)
|
|
||||||
else:
|
|
||||||
num_lines_to_insert = random.randint(1, 3)
|
|
||||||
lines = _InsertRandomLocationReload(lines, num_lines_to_insert)
|
|
||||||
return ';\n'.join(lines)
|
|
||||||
|
|
||||||
|
|
||||||
def _InsertRandomLocationReloadsWithinMarkers(file_data,
|
|
||||||
insert_everywhere=False):
|
|
||||||
"""Inserts random location.reload() statements in the file.
|
|
||||||
|
|
||||||
We can insert statements after other statements (e.g. after ; and newline).
|
|
||||||
We only consider the text between the "reload injection markers" so that we
|
|
||||||
can avoid injecting location.reload()s into the HTML or after variable
|
|
||||||
declarations, for instance. Therefore, the markers must be present in the
|
|
||||||
file data passed into this function.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
file_data: The template file data as a string.
|
|
||||||
insert_everywhere: If true, will replace at all possible injection points.
|
|
||||||
If false, we will randomly choose 1-3 injection points.
|
|
||||||
"""
|
|
||||||
start_marker = '// START_OF_POSSIBLE_INJECTED_LOCATION_RELOADS'
|
|
||||||
end_marker = '// END_OF_POSSIBLE_INJECTED_LOCATION_RELOADS'
|
|
||||||
within_markers_regex = re.compile(start_marker + '(.+)' + end_marker,
|
|
||||||
re.DOTALL)
|
|
||||||
within_markers = within_markers_regex.search(file_data)
|
|
||||||
if not within_markers:
|
|
||||||
raise MissingParameterException(
|
|
||||||
'Missing %s and/or %s in template.' % (start_marker, end_marker))
|
|
||||||
|
|
||||||
# Now insert the location.reload()s.
|
|
||||||
modified_data = _InsertRandomLocationReloads(
|
|
||||||
within_markers.group(1), insert_everywhere)
|
|
||||||
|
|
||||||
return within_markers_regex.sub(modified_data, file_data)
|
|
||||||
|
|
||||||
|
|
||||||
def Fuzz(file_data):
|
|
||||||
"""Fuzzes the passed in template."""
|
|
||||||
file_data = file_data.decode('utf-8')
|
|
||||||
|
|
||||||
# Generate a bunch of random numbers and encode them into the page. Since the
|
|
||||||
# values get hard-coded into the page the page's choices will be reproducible.
|
|
||||||
file_data = FillInParameter('ARRAY_OF_RANDOM_ROLLS',
|
|
||||||
_ArrayOfRandomRolls(500),
|
|
||||||
file_data)
|
|
||||||
|
|
||||||
# Randomly decide how to fuzz SDP data.
|
|
||||||
file_data = FillInParameter('REQUEST_AUDIO_AND_VIDEO',
|
|
||||||
_RandomAudioOrVideo(),
|
|
||||||
file_data)
|
|
||||||
file_data = FillInParameter('TRANSFORM_OFFER_SDP',
|
|
||||||
_RandomSdpTransform(),
|
|
||||||
file_data)
|
|
||||||
file_data = FillInParameter('TRANSFORM_ANSWER_SDP',
|
|
||||||
_RandomSdpTransform(),
|
|
||||||
file_data)
|
|
||||||
|
|
||||||
# Random location.reload() calls in the call sequence can be challenging for
|
|
||||||
# the code to deal with, so insert some here and there.
|
|
||||||
if random.random() < 0.3:
|
|
||||||
file_data = _InsertRandomLocationReloadsWithinMarkers(file_data)
|
|
||||||
|
|
||||||
return file_data
|
|
||||||
|
|
||||||
|
|
||||||
def MakeWorkingFile(file_data):
|
|
||||||
"""Fills in arguments to make a basic working file.
|
|
||||||
|
|
||||||
Used for ensuring that the basic template is standards-compliant.
|
|
||||||
"""
|
|
||||||
file_data = file_data.decode('utf-8')
|
|
||||||
|
|
||||||
file_data = FillInParameter('ARRAY_OF_RANDOM_ROLLS',
|
|
||||||
_ArrayOfRandomRolls(500),
|
|
||||||
file_data)
|
|
||||||
file_data = FillInParameter('REQUEST_AUDIO_AND_VIDEO',
|
|
||||||
'{ video: true, audio: true }',
|
|
||||||
file_data)
|
|
||||||
file_data = FillInParameter('TRANSFORM_OFFER_SDP',
|
|
||||||
_ReturnFirstArgument(),
|
|
||||||
file_data)
|
|
||||||
file_data = FillInParameter('TRANSFORM_ANSWER_SDP',
|
|
||||||
_ReturnFirstArgument(),
|
|
||||||
file_data)
|
|
||||||
|
|
||||||
return file_data
|
|
@@ -1,87 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
#-*- coding: utf-8 -*-
|
|
||||||
# Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
|
||||||
#
|
|
||||||
# Use of this source code is governed by a BSD-style license
|
|
||||||
# that can be found in the LICENSE file in the root of the source
|
|
||||||
# tree. An additional intellectual property rights grant can be found
|
|
||||||
# in the file PATENTS. All contributing project authors may
|
|
||||||
# be found in the AUTHORS file in the root of the source tree.
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
import peerconnection_fuzz
|
|
||||||
|
|
||||||
SAMPLE_TEMPLATE = """
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>WebRTC PeerConnection Fuzz Test Template</title>
|
|
||||||
<script type="text/javascript">
|
|
||||||
var gFirstConnection = null;
|
|
||||||
|
|
||||||
// START_OF_POSSIBLE_INJECTED_LOCATION_RELOADS
|
|
||||||
function startTest() {
|
|
||||||
navigator.webkitGetUserMedia(REQUEST_AUDIO_AND_VIDEO,
|
|
||||||
getUserMediaOkCallback,
|
|
||||||
getUserMediaFailedCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
function callUsingStream(localStream) {
|
|
||||||
gFirstConnection.createOffer(onOfferCreated);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onIceCandidateToFirst(event) {
|
|
||||||
if (event.candidate) {
|
|
||||||
var candidate = new RTCIceCandidate(event.candidate);
|
|
||||||
gSecondConnection.addIceCandidate(candidate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// END_OF_POSSIBLE_INJECTED_LOCATION_RELOADS
|
|
||||||
</script>
|
|
||||||
</head>"""
|
|
||||||
|
|
||||||
RELOADED_TEMPLATE = """
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>WebRTC PeerConnection Fuzz Test Template</title>
|
|
||||||
<script type="text/javascript">
|
|
||||||
var gFirstConnection = null;
|
|
||||||
|
|
||||||
|
|
||||||
function startTest() {
|
|
||||||
navigator.webkitGetUserMedia(REQUEST_AUDIO_AND_VIDEO,
|
|
||||||
getUserMediaOkCallback,
|
|
||||||
getUserMediaFailedCallback);
|
|
||||||
location.reload();
|
|
||||||
}
|
|
||||||
|
|
||||||
function callUsingStream(localStream) {
|
|
||||||
gFirstConnection.createOffer(onOfferCreated);
|
|
||||||
location.reload();
|
|
||||||
}
|
|
||||||
|
|
||||||
function onIceCandidateToFirst(event) {
|
|
||||||
if (event.candidate) {
|
|
||||||
var candidate = new RTCIceCandidate(event.candidate);
|
|
||||||
location.reload();
|
|
||||||
gSecondConnection.addIceCandidate(candidate);
|
|
||||||
location.reload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</head>"""
|
|
||||||
|
|
||||||
class PeerConnectionFuzzerTest(unittest.TestCase):
|
|
||||||
def testInsertRandomReloadsInsertsAtTheRightPlace(self):
|
|
||||||
"""Tests we can insert location.reload() in the right places.
|
|
||||||
|
|
||||||
Only tests the case where we replace all since the other case is random.
|
|
||||||
"""
|
|
||||||
result = peerconnection_fuzz._InsertRandomLocationReloadsWithinMarkers(
|
|
||||||
SAMPLE_TEMPLATE, replace_all=True)
|
|
||||||
self.assertEquals(RELOADED_TEMPLATE, result,
|
|
||||||
'Got "%s", should be "%s"' % (result, RELOADED_TEMPLATE))
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
Reference in New Issue
Block a user