Skip to content

Commit d37a8ed

Browse files
ManishearthV8-internal LUCI CQ
authored andcommitted
[intl] Add fuzz support for Intl.Locale
This fills in some support for Intl.Locale. There's still work to be done, but this covers most of the API. Bug: 450083673 Change-Id: I7b2f899b7d2a8ff44a10a7ecea5f8a906a6a6964 Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/8881013 Reviewed-by: Matthias Liedtke <mliedtke@google.com> Commit-Queue: Manish Goregaokar <manishearth@google.com>
1 parent 948e9fd commit d37a8ed

File tree

3 files changed

+153
-8
lines changed

3 files changed

+153
-8
lines changed

Sources/Fuzzilli/Base/ProgramBuilder.swift

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5286,12 +5286,24 @@ public class ProgramBuilder {
52865286

52875287
@discardableResult
52885288
static func constructIntlLocaleString() -> String {
5289+
// TODO(Manishearth) Generate more complicated locale strings, not just language strings
5290+
return constructIntlLanguageString()
5291+
}
5292+
5293+
5294+
@discardableResult
5295+
static func constructIntlLanguageString() -> String {
52895296
// TODO(Manishearth) Generate more interesting locales than just the builtins
52905297
return chooseUniform(from: Locale.availableIdentifiers)
52915298
}
52925299

52935300
// Obtained by calling Intl.supportedValuesOf("unit") in a browser
52945301
fileprivate static let allUnits = ["acre", "bit", "byte", "celsius", "centimeter", "day", "degree", "fahrenheit", "fluid-ounce", "foot", "gallon", "gigabit", "gigabyte", "gram", "hectare", "hour", "inch", "kilobit", "kilobyte", "kilogram", "kilometer", "liter", "megabit", "megabyte", "meter", "microsecond", "mile", "mile-scandinavian", "milliliter", "millimeter", "millisecond", "minute", "month", "nanosecond", "ounce", "percent", "petabyte", "pound", "second", "stone", "terabit", "terabyte", "week", "yard", "year"]
5302+
// https://en.wikipedia.org/wiki/ISO_15924#List_of_codes
5303+
// Unfortunately this list grows over time, but constructIntlScript can at least randomly generate other four-char script codes
5304+
fileprivate static let allScripts = ["Adlm", "Afak", "Aghb", "Ahom", "Arab", "Aran", "Armi", "Armn", "Avst", "Bali", "Bamu", "Bass", "Batk", "Beng", "Berf", "Bhks", "Blis", "Bopo", "Brah", "Brai", "Bugi", "Buhd", "Cakm", "Cans", "Cari", "Cham", "Cher", "Chis", "Chrs", "Cirt", "Copt", "Cpmn", "Cprt", "Cyrl", "Cyrs", "Deva", "Diak", "Dogr", "Dsrt", "Dupl", "Egyd", "Egyh", "Egyp", "Elba", "Elym", "Ethi", "Gara", "Geok", "Geor", "Glag", "Gong", "Gonm", "Goth", "Gran", "Grek", "Gujr", "Gukh", "Guru", "Hanb", "Hang", "Hani", "Hano", "Hans", "Hant", "Hatr", "Hebr", "Hira", "Hluw", "Hmng", "Hmnp", "Hntl", "Hrkt", "Hung", "Inds", "Ital", "Jamo", "Java", "Jpan", "Jurc", "Kali", "Kana", "Kawi", "Khar", "Khmr", "Khoj", "Kitl", "Kits", "Knda", "Kore", "Kpel", "Krai", "Kthi", "Lana", "Laoo", "Latf", "Latg", "Latn", "Leke", "Lepc", "Limb", "Lina", "Linb", "Lisu", "Loma", "Lyci", "Lydi", "Mahj", "Maka", "Mand", "Mani", "Marc", "Maya", "Medf", "Mend", "Merc", "Mero", "Mlym", "Modi", "Mong", "Moon", "Mroo", "Mtei", "Mult", "Mymr", "Nagm", "Nand", "Narb", "Nbat", "Newa", "Nkdb", "Nkgb", "Nkoo", "Nshu", "Ogam", "Olck", "Onao", "Orkh", "Orya", "Osge", "Osma", "Ougr", "Palm", "Pauc", "Pcun", "Pelm", "Perm", "Phag", "Phli", "Phlp", "Phlv", "Phnx", "Piqd", "Plrd", "Prti", "Psin", "Qaaa-Qabx", "Ranj", "Rjng", "Rohg", "Roro", "Runr", "Samr", "Sara", "Sarb", "Saur", "Seal", "Sgnw", "Shaw", "Shrd", "Shui", "Sidd", "Sidt", "Sind", "Sinh", "Sogd", "Sogo", "Sora", "Soyo", "Sund", "Sunu", "Sylo", "Syrc", "Syre", "Syrj", "Syrn", "Tagb", "Takr", "Tale", "Talu", "Taml", "Tang", "Tavt", "Tayo", "Telu", "Teng", "Tfng", "Tglg", "Thaa", "Thai", "Tibt", "Tirh", "Tnsa", "Todr", "Tols", "Toto", "Tutg", "Ugar", "Vaii", "Visp", "Vith", "Wara", "Wcho", "Wole", "Xpeo", "Xsux", "Yezi", "Yiii", "Zanb", "Zinh", "Zmth", "Zsye", "Zsym", "Zxxx", "Zyyy", "Zzzz"]
5305+
fileprivate static let allAlpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
5306+
fileprivate static let allAlphaNum = allAlpha + "0123456789"
52955307

52965308
@discardableResult
52975309
static func constructIntlUnit() -> String {
@@ -5304,6 +5316,60 @@ public class ProgramBuilder {
53045316
}
53055317
}
53065318

5319+
5320+
@discardableResult
5321+
static func constructIntlScriptString() -> String {
5322+
if probability(0.7) {
5323+
return chooseUniform(from: allScripts)
5324+
} else {
5325+
return String((0..<4).map { _ in allAlpha.randomElement()! })
5326+
}
5327+
}
5328+
5329+
@discardableResult
5330+
static func constructIntlRegionString() -> String {
5331+
// either two letters or three digits
5332+
if probability(0.5) {
5333+
return String((0..<2).map { _ in allAlpha.randomElement()! })
5334+
} else {
5335+
return String(format: "%03d", Int.random(in: 0...999))
5336+
}
5337+
}
5338+
5339+
@discardableResult
5340+
private static func constructSingleIntlVariantString() -> String {
5341+
// 5-8 alphanumerics or a digit and 3 alphanumerics
5342+
if probability(0.5) {
5343+
let count = Int.random(in: 5...8)
5344+
return String((0..<count).map { _ in allAlphaNum.randomElement()! })
5345+
} else {
5346+
let alpha = String((0..<3).map { _ in allAlphaNum.randomElement()! })
5347+
return "\(Int.random(in: 0...9))\(alpha)"
5348+
}
5349+
}
5350+
5351+
@discardableResult
5352+
static func constructIntlVariantString() -> String {
5353+
if probability(0.9) {
5354+
return constructSingleIntlVariantString()
5355+
} else {
5356+
return "\(constructSingleIntlVariantString())-\(constructIntlVariantString())"
5357+
}
5358+
}
5359+
5360+
@discardableResult
5361+
func constructIntlLocale() -> Variable {
5362+
let intl = createNamedVariable(forBuiltin: "Intl")
5363+
let constructor = getProperty("Locale", of: intl)
5364+
5365+
var args: [Variable] = []
5366+
args.append(findOrGenerateType(.jsIntlLocaleString))
5367+
if probability(0.7) {
5368+
args.append(createOptionsBag(.jsIntlLocaleSettings))
5369+
}
5370+
return construct(constructor, withArgs: args)
5371+
}
5372+
53075373
// Generic generators for Intl types.
53085374
private func constructIntlType(type: String, optionsBag: OptionsBag) -> Variable {
53095375
let intl = createNamedVariable(forBuiltin: "Intl")

Sources/Fuzzilli/CodeGen/CodeGenerators.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ public let CodeGenerators: [CodeGenerator] = [
309309
},
310310

311311
CodeGenerator("BuiltinIntlGenerator") { b in
312-
let _ = chooseUniform(from: [b.constructIntlDateTimeFormat, b.constructIntlCollator, b.constructIntlListFormat, b.constructIntlNumberFormat, b.constructIntlPluralRules, b.constructIntlRelativeTimeFormat, b.constructIntlSegmenter])()
312+
let _ = chooseUniform(from: [b.constructIntlDateTimeFormat, b.constructIntlCollator, b.constructIntlListFormat, b.constructIntlLocale, b.constructIntlNumberFormat, b.constructIntlPluralRules, b.constructIntlRelativeTimeFormat, b.constructIntlSegmenter])()
313313
},
314314

315315
CodeGenerator("HexGenerator") { b in

Sources/Fuzzilli/Environment/JavaScriptEnvironment.swift

Lines changed: 86 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,9 @@ public class JavaScriptEnvironment: ComponentBase {
433433
registerObjectGroup(.jsIntlListFormat)
434434
registerObjectGroup(.jsIntlListFormatConstructor)
435435
registerObjectGroup(.jsIntlListFormatPrototype)
436+
registerObjectGroup(.jsIntlLocale)
437+
registerObjectGroup(.jsIntlLocaleConstructor)
438+
registerObjectGroup(.jsIntlLocalePrototype)
436439
registerObjectGroup(.jsIntlNumberFormat)
437440
registerObjectGroup(.jsIntlNumberFormatConstructor)
438441
registerObjectGroup(.jsIntlNumberFormatPrototype)
@@ -476,6 +479,7 @@ public class JavaScriptEnvironment: ComponentBase {
476479
registerEnumeration(OptionsBag.jsIntlFullLongMediumShort)
477480
registerEnumeration(OptionsBag.jsIntlCollatorUsageEnum)
478481
registerEnumeration(OptionsBag.jsIntlCollationEnum)
482+
registerEnumeration(OptionsBag.jsIntlCollationTypeEnum)
479483
registerEnumeration(OptionsBag.jsIntlCaseFirstEnum)
480484
registerEnumeration(OptionsBag.jsIntlCollatorSensitivityEnum)
481485
registerEnumeration(OptionsBag.jsIntlListFormatTypeEnum)
@@ -511,6 +515,7 @@ public class JavaScriptEnvironment: ComponentBase {
511515
registerOptionsBag(.jsIntlDateTimeFormatSettings)
512516
registerOptionsBag(.jsIntlCollatorSettings)
513517
registerOptionsBag(.jsIntlListFormatSettings)
518+
registerOptionsBag(.jsIntlLocaleSettings)
514519
registerOptionsBag(.jsIntlNumberFormatSettings)
515520
registerOptionsBag(.jsIntlPluralRulesSettings)
516521
registerOptionsBag(.jsIntlRelativeTimeFormatSettings)
@@ -536,8 +541,12 @@ public class JavaScriptEnvironment: ComponentBase {
536541
return ProgramBuilder.randomUTCOffsetString(mayHaveSeconds: true)
537542
}
538543
})
539-
addNamedStringGenerator(forType: .jsIntlLocaleLike, with: { ProgramBuilder.constructIntlLocaleString() })
540-
addNamedStringGenerator(forType: .jsIntlUnit, with: { ProgramBuilder.constructIntlUnit() })
544+
addNamedStringGenerator(forType: .jsIntlLocaleString, with: { ProgramBuilder.constructIntlLocaleString() })
545+
addNamedStringGenerator(forType: .jsIntlLanguageString, with: { ProgramBuilder.constructIntlLanguageString() })
546+
addNamedStringGenerator(forType: .jsIntlScriptString, with: { ProgramBuilder.constructIntlScriptString() })
547+
addNamedStringGenerator(forType: .jsIntlRegionString, with: { ProgramBuilder.constructIntlRegionString() })
548+
addNamedStringGenerator(forType: .jsIntlVariantString, with: { ProgramBuilder.constructIntlVariantString() })
549+
addNamedStringGenerator(forType: .jsIntlUnitString, with: { ProgramBuilder.constructIntlUnit() })
541550

542551
// Temporal types are produced by a large number of methods; which means findOrGenerateType(), when asked to produce
543552
// a Temporal type, will tend towards trying to call a method on another Temporal type, which needs more Temporal types,
@@ -3012,7 +3021,10 @@ extension OptionsBag {
30123021
// Intl
30133022
extension ILType {
30143023
// Intl types
3015-
static let jsIntlObject = ILType.object(ofGroup: "Intl", withProperties: ["DateTimeFormat", "Collator", "ListFormat", "NumberFormat", "PluralRules", "RelativeTimeFormat", "Segmenter"], withMethods: ["getCanonicalLocales", "supportedValuesOf"])
3024+
static let jsIntlObject = ILType.object(ofGroup: "Intl", withProperties: ["DateTimeFormat", "Collator", "ListFormat", "Locale", "NumberFormat", "PluralRules", "RelativeTimeFormat", "Segmenter"], withMethods: ["getCanonicalLocales", "supportedValuesOf"])
3025+
3026+
static let jsIntlLocale = ILType.object(ofGroup: "Intl.Locale", withProperties: ["baseName", "calendar", "caseFirst", "collation", "hourCycle", "language", "numberingSystem", "numeric", "region", "script", "variants"], withMethods: ["getCalendars", "getCollations", "getHourCycles", "getNumberingSystems", "getTextInfo", "getTimeZones", "getWeekInfo", "maximize", "minimize", "toString"])
3027+
static let jsIntlLocaleConstructor = ILType.functionAndConstructor([.plain(.jsIntlLocaleString), .opt(OptionsBag.jsIntlLocaleSettings.group.instanceType)] => .jsIntlLocale) + .object(ofGroup: "IntlLocaleConstructor", withProperties: ["prototype"], withMethods: [])
30163028

30173029
static let jsIntlCollator = ILType.object(ofGroup: "Intl.Collator", withProperties: [], withMethods: ["compare", "resolvedOptions"])
30183030
static let jsIntlCollatorConstructor = ILType.functionAndConstructor([.opt(.jsIntlLocaleLike), .opt(OptionsBag.jsIntlCollatorSettings.group.instanceType)] => .jsIntlCollator) + .object(ofGroup: "IntlCollatorConstructor", withProperties: ["prototype"], withMethods: ["supportedLocalesOf"])
@@ -3037,8 +3049,14 @@ extension ILType {
30373049

30383050
static let jsIntlSegmenterSegments = ILType.object(ofGroup: "IntlSegmenterSegments", withProperties: [], withMethods: ["containing"])
30393051

3040-
static let jsIntlLocaleLike = ILType.namedString(ofName: "IntlLocaleString")
3041-
static let jsIntlUnit = ILType.namedString(ofName: "IntlUnitString")
3052+
static let jsIntlLocaleString = ILType.namedString(ofName: "IntlLocaleString")
3053+
static let jsIntlLanguageString = ILType.namedString(ofName: "IntlLanguageString")
3054+
static let jsIntlScriptString = ILType.namedString(ofName: "IntlScriptString")
3055+
static let jsIntlRegionString = ILType.namedString(ofName: "IntlRegionString")
3056+
static let jsIntlVariantString = ILType.namedString(ofName: "IntlVariantString")
3057+
// TODO: locale-likes are actually supposed to be a locale string, an Intl.Locale object, or an array of the same
3058+
static let jsIntlLocaleLike = ILType.jsIntlLocaleString
3059+
static let jsIntlUnitString = ILType.namedString(ofName: "IntlUnitString")
30423060
}
30433061

30443062
extension ObjectGroup {
@@ -3051,6 +3069,7 @@ extension ObjectGroup {
30513069
"Collator" : .jsIntlCollatorConstructor,
30523070
"DateTimeFormat" : .jsIntlDateTimeFormatConstructor,
30533071
"ListFormat" : .jsIntlListFormatConstructor,
3072+
"Locale" : .jsIntlLocaleConstructor,
30543073
"NumberFormat" : .jsIntlNumberFormatConstructor,
30553074
"PluralRules" : .jsIntlPluralRulesConstructor,
30563075
"RelativeTimeFormat" : .jsIntlRelativeTimeFormatConstructor,
@@ -3157,6 +3176,48 @@ extension ObjectGroup {
31573176
]
31583177
)
31593178

3179+
static let jsIntlLocale = ObjectGroup(
3180+
name: "Intl.Locale",
3181+
instanceType: .jsIntlLocale,
3182+
properties: [
3183+
"baseName": .string,
3184+
"calendar": .string,
3185+
"caseFirst": .string,
3186+
"collation": .string,
3187+
"hourCycle": .string,
3188+
"language": .string,
3189+
"numberingSystem": .string,
3190+
"numeric": .string,
3191+
"region": .string,
3192+
"script": .string,
3193+
"variants": .string,
3194+
],
3195+
methods: [
3196+
"getCalendars": [] => .jsArray,
3197+
"getCollations": [] => .jsArray,
3198+
"getHourCycles": [] => .jsArray,
3199+
"getNumberingSystems": [] => .jsArray,
3200+
"getTextInfo": [] => .jsArray,
3201+
"getTimeZones": [] => .jsArray,
3202+
"getWeekInfo": [] => .object(),
3203+
"maximize": [] => .jsIntlLocale,
3204+
"minimize": [] => .jsIntlLocale,
3205+
"toString": [] => .string,
3206+
]
3207+
)
3208+
3209+
static let jsIntlLocalePrototype = createPrototypeObjectGroup(jsIntlLocale)
3210+
3211+
static let jsIntlLocaleConstructor = ObjectGroup(
3212+
name: "IntlLocaleConstructor",
3213+
constructorPath: "Intl.Locale",
3214+
instanceType: .jsIntlLocaleConstructor,
3215+
properties: [
3216+
"prototype" : jsIntlLocalePrototype.instanceType,
3217+
],
3218+
methods: [:]
3219+
)
3220+
31603221
fileprivate static func numberFormatSignature(_ returnType: ILType) -> [Signature] {
31613222
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/format
31623223
[ILType.number, .bigint, .string].map {
@@ -3301,6 +3362,7 @@ extension OptionsBag {
33013362
fileprivate static let jsIntlFullLongMediumShort = ILType.enumeration(ofName: "IntlFullLongMediumShort", withValues: ["full", "long", "medium", "short"])
33023363
fileprivate static let jsIntlCollatorUsageEnum = ILType.enumeration(ofName: "IntlCollatorUsage", withValues: ["sort", "search"])
33033364
fileprivate static let jsIntlCollationEnum = ILType.enumeration(ofName: "IntlCollation", withValues: ["emoji", "pinyin", "stroke"])
3365+
fileprivate static let jsIntlCollationTypeEnum = ILType.enumeration(ofName: "IntlCollationType", withValues: ["compat", "emoji", "eor", "phonebk", "pinyin", "searchjl", "stroke", "trad", "unihan", "zhuyin"])
33043366
fileprivate static let jsIntlCaseFirstEnum = ILType.enumeration(ofName: "IntlCaseFirst", withValues: ["upper", "lower", "false"])
33053367
fileprivate static let jsIntlCollatorSensitivityEnum = ILType.enumeration(ofName: "IntlCollatorSensitivity", withValues: ["base", "accent", "case", "variant"])
33063368
fileprivate static let jsIntlListFormatTypeEnum = ILType.enumeration(ofName: "IntlListFormatTypeEnum", withValues: ["conjunction", "disjunction", "unit"])
@@ -3319,7 +3381,7 @@ extension OptionsBag {
33193381

33203382
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#parameters
33213383
static let jsIntlDateTimeFormatSettings = OptionsBag(
3322-
name: "IntlLocaleSettings",
3384+
name: "IntlDateTimeFormatSettings",
33233385
properties: [
33243386
// Locale options
33253387
"localeMatcher": jsIntlLocaleMatcherEnum,
@@ -3371,6 +3433,23 @@ extension OptionsBag {
33713433
]
33723434
)
33733435

3436+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/Locale#options
3437+
static let jsIntlLocaleSettings = OptionsBag(
3438+
name: "IntlLocaleSettings",
3439+
properties: [
3440+
"language": .jsIntlLanguageString,
3441+
"script": .jsIntlScriptString,
3442+
"region": .jsIntlRegionString,
3443+
"variants": .jsIntlVariantString,
3444+
"calendar": .jsTemporalCalendarEnum,
3445+
"collation": jsIntlCollationTypeEnum,
3446+
"numberingSystem": jsIntlNumberingSystemEnum,
3447+
"caseFirst": jsIntlCaseFirstEnum,
3448+
"hourCycle": jsIntlHourCycleEnum,
3449+
"numeric": .boolean,
3450+
]
3451+
)
3452+
33743453
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#options
33753454
static let jsIntlNumberFormatSettings = OptionsBag(
33763455
name: "IntlNumberFormatSettings",
@@ -3383,7 +3462,7 @@ extension OptionsBag {
33833462
"currency": jsIntlCurrencySystemEnum,
33843463
"currencyDisplay": jsIntlCurrencyDisplayEnum,
33853464
"currencySign": jsIntlCurrencySignEnum,
3386-
"unit": .jsIntlUnit,
3465+
"unit": .jsIntlUnitString,
33873466
"unitDisplay": jsIntlLongShortNarrowEnum,
33883467
// digit options
33893468
"minimumIntegerDigits": .integer,

0 commit comments

Comments
 (0)