~mmach/netext73/webkit2gtk

« back to all changes in this revision

Viewing changes to Source/JavaScriptCore/runtime/FuzzerPredictions.cpp

  • Committer: mmach
  • Date: 2023-06-16 17:21:37 UTC
  • Revision ID: netbit73@gmail.com-20230616172137-2rqx6yr96ga9g3kp
1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2019 Apple Inc. All rights reserved.
 
3
 *
 
4
 * Redistribution and use in source and binary forms, with or without
 
5
 * modification, are permitted provided that the following conditions
 
6
 * are met:
 
7
 * 1. Redistributions of source code must retain the above copyright
 
8
 *    notice, this list of conditions and the following disclaimer.
 
9
 * 2. Redistributions in binary form must reproduce the above copyright
 
10
 *    notice, this list of conditions and the following disclaimer in the
 
11
 *    documentation and/or other materials provided with the distribution.
 
12
 *
 
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
24
 */
 
25
 
 
26
#include "config.h"
 
27
#include "FuzzerPredictions.h"
 
28
 
 
29
namespace JSC {
 
30
 
 
31
static String readFileIntoString(const char* fileName)
 
32
{
 
33
    FILE* file = fopen(fileName, "r");
 
34
    RELEASE_ASSERT_WITH_MESSAGE(file, "Failed to open file %s", fileName);
 
35
    RELEASE_ASSERT(fseek(file, 0, SEEK_END) != -1);
 
36
    long bufferCapacity = ftell(file);
 
37
    RELEASE_ASSERT(bufferCapacity != -1);
 
38
    RELEASE_ASSERT(fseek(file, 0, SEEK_SET) != -1);
 
39
    Vector<char> buffer;
 
40
    buffer.resize(bufferCapacity);
 
41
    size_t readSize = fread(buffer.data(), 1, buffer.size(), file);
 
42
    fclose(file);
 
43
    RELEASE_ASSERT(readSize == buffer.size());
 
44
    return String(buffer.data(), buffer.size());
 
45
}
 
46
 
 
47
FuzzerPredictions::FuzzerPredictions(const char* filename)
 
48
{
 
49
    RELEASE_ASSERT_WITH_MESSAGE(filename, "prediction file must be specified using --fuzzerPredictionsFile=");
 
50
 
 
51
    String predictions = readFileIntoString(filename);
 
52
    const Vector<String>& lines = predictions.split('\n');
 
53
    for (const auto& line : lines) {
 
54
        // Predictions are stored in a text file, one prediction per line in the colon delimited format:
 
55
        // <lookup key>:<prediction in hex without leading 0x>
 
56
        // The lookup key is a pipe separated string with the format:
 
57
        // <filename>|<opcode>|<start offset>|<end offset>
 
58
 
 
59
        // The start and end offsets are 7-bit unsigned integers.
 
60
        // If start offset > 127, then both start and end offsets are 0.
 
61
        // If end offset > 127, then the end offset is 0.
 
62
 
 
63
        // Example predictions:
 
64
        // foo.js|op_construct|702|721:1000084
 
65
        // foo.js|op_call|748|760:408800
 
66
        // foo.js|op_bitnot|770|770:280000000
 
67
 
 
68
        // Predictions can be generated using PredictionFileCreatingFuzzerAgent.
 
69
        // Some opcodes are aliased together to make generating the predictions more straightforward.
 
70
        // For the aliases see: FileBasedFuzzerAgentBase::opcodeAliasForLookupKey()
 
71
 
 
72
        // FIXME: The current implementation only supports one prediction per lookup key.
 
73
 
 
74
        const Vector<String>& lineParts = line.split(':');
 
75
        RELEASE_ASSERT_WITH_MESSAGE(lineParts.size() == 2, "Expected line with two parts delimited by a colon. Found line with %lu parts.", lineParts.size());
 
76
        const String& lookupKey = lineParts[0];
 
77
        const String& predictionString = lineParts[1];
 
78
        bool ok;
 
79
        SpeculatedType prediction = predictionString.toUInt64Strict(&ok, 0x10);
 
80
        RELEASE_ASSERT_WITH_MESSAGE(ok, "Could not parse prediction from '%s'", predictionString.utf8().data());
 
81
        RELEASE_ASSERT(speculationChecked(prediction, SpecFullTop));
 
82
        m_predictions.set(lookupKey, prediction);
 
83
    }
 
84
}
 
85
 
 
86
Optional<SpeculatedType> FuzzerPredictions::predictionFor(const String& key)
 
87
{
 
88
    auto it = m_predictions.find(key);
 
89
    if (it == m_predictions.end())
 
90
        return WTF::nullopt;
 
91
    return it->value;
 
92
}
 
93
 
 
94
FuzzerPredictions& ensureGlobalFuzzerPredictions()
 
95
{
 
96
    static LazyNeverDestroyed<FuzzerPredictions> fuzzerPredictions;
 
97
    static std::once_flag initializeFuzzerPredictionsFlag;
 
98
    std::call_once(initializeFuzzerPredictionsFlag, [] {
 
99
        const char* fuzzerPredictionsFilename = Options::fuzzerPredictionsFile();
 
100
        fuzzerPredictions.construct(fuzzerPredictionsFilename);
 
101
    });
 
102
    return fuzzerPredictions;
 
103
}
 
104
 
 
105
} // namespace JSC