Skip to content

Commit e12a171

Browse files
LiedtkeV8-internal LUCI CQ
authored andcommitted
[environment] Register Intl.DisplayNames and its builtins
and add a custom generator for Intl.DisplayNames.prototype.of() as it contains a tight coupling between the constructor arguments and the code provided to the "of" function as an argument. Bug: 487347678 Change-Id: Ia0ffd3f51599b501a6855b07931249abcf777984 Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/9063878 Commit-Queue: Matthias Liedtke <mliedtke@google.com> Reviewed-by: Manish Goregaokar <manishearth@google.com>
1 parent c64357c commit e12a171

3 files changed

Lines changed: 142 additions & 13 deletions

File tree

Sources/Fuzzilli/Base/ProgramBuilder.swift

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5019,22 +5019,28 @@ public class ProgramBuilder {
50195019
// so we instead register a generator that allows the fuzzer a greater chance of generating
50205020
// one when needed.
50215021
//
5022-
// These can be registered on the JavaScriptEnvironment with addProducingGenerator()
5022+
// These can be registered on the JavaScriptEnvironment with addProducingGenerator().
5023+
// argument `predefined`: Provide values that should be used for the given properties of the
5024+
// options bag (if present) instead of finding or generating random values for them. The
5025+
// property might still be filtered out.
50235026
@discardableResult
5024-
func createOptionsBag(_ bag: OptionsBag) -> Variable {
5027+
func createOptionsBag(_ bag: OptionsBag, predefined: [String: Variable] = [:]) -> Variable {
50255028
// We run .filter() to pick a subset of fields, but we generally want to set as many as possible
50265029
// and let the mutator prune things
5027-
let dict: [String : Variable] = bag.properties.filter {_ in probability(0.8)}.mapValues {
5028-
if $0.isEnumeration {
5029-
return loadEnum($0)
5030+
let dict = [String : Variable](uniqueKeysWithValues: bag.properties.filter {_ in probability(0.8)}.map {
5031+
let (propertyName, type) = $0
5032+
if let predefinedVar = predefined[propertyName] {
5033+
return (propertyName, predefinedVar)
5034+
} else if type.isEnumeration {
5035+
return (propertyName, loadEnum(type))
50305036
// relativeTo doesn't have an ObjectGroup so we cannot just register a producingGenerator for it
5031-
} else if $0.Is(OptionsBag.jsTemporalRelativeTo) {
5032-
return findOrGenerateType(chooseUniform(from: [.jsTemporalZonedDateTime, .jsTemporalPlainDateTime,
5033-
.jsTemporalPlainDate, .string]))
5037+
} else if type.Is(OptionsBag.jsTemporalRelativeTo) {
5038+
return (propertyName, findOrGenerateType(chooseUniform(from: [.jsTemporalZonedDateTime, .jsTemporalPlainDateTime,
5039+
.jsTemporalPlainDate, .string])))
50345040
} else {
5035-
return findOrGenerateType($0)
5041+
return (propertyName, findOrGenerateType(type))
50365042
}
5037-
}
5043+
})
50385044
return createObject(with: dict)
50395045
}
50405046

@@ -5403,6 +5409,29 @@ public class ProgramBuilder {
54035409
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"]
54045410
fileprivate static let allAlpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
54055411
fileprivate static let allAlphaNum = allAlpha + "0123456789"
5412+
fileprivate static let allRegionsTwoDigit = [
5413+
"AD", "AE", "AF", "AG", "AI", "AL", "AM", "AO", "AQ", "AR", "AS", "AT",
5414+
"AU", "AW", "AX", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI",
5415+
"BJ", "BL", "BM", "BN", "BO", "BQ", "BR", "BS", "BT", "BV", "BW", "BY",
5416+
"BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN",
5417+
"CO", "CR", "CU", "CV", "CW", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM",
5418+
"DO", "DZ", "EC", "EE", "EG", "EH", "ER", "ES", "ET", "FI", "FJ", "FK",
5419+
"FM", "FO", "FR", "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", "GL",
5420+
"GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM",
5421+
"HN", "HR", "HT", "HU", "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR",
5422+
"IS", "IT", "JE", "JM", "JO", "JP", "KE", "KG", "KH", "KI", "KM", "KN",
5423+
"KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS",
5424+
"LT", "LU", "LV", "LY", "MA", "MC", "MD", "ME", "MF", "MG", "MH", "MK",
5425+
"ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW",
5426+
"MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP",
5427+
"NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM",
5428+
"PN", "PR", "PS", "PT", "PW", "PY", "QA", "RE", "RO", "RS", "RU", "RW",
5429+
"SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM",
5430+
"SN", "SO", "SR", "SS", "ST", "SV", "SX", "SY", "SZ", "TC", "TD", "TF",
5431+
"TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TO", "TR", "TT", "TV", "TW",
5432+
"TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI",
5433+
"VN", "VU", "WF", "WS", "YE", "YT", "ZA", "ZM", "ZW",
5434+
]
54065435

54075436
@discardableResult
54085437
static func constructIntlUnit() -> String {
@@ -5429,7 +5458,7 @@ public class ProgramBuilder {
54295458
static func constructIntlRegionString() -> String {
54305459
// either two letters or three digits
54315460
if probability(0.5) {
5432-
return String((0..<2).map { _ in allAlpha.randomElement()! })
5461+
return allRegionsTwoDigit.randomElement()!
54335462
} else {
54345463
return String(format: "%03d", Int.random(in: 0...999))
54355464
}
@@ -5495,6 +5524,11 @@ public class ProgramBuilder {
54955524
return constructIntlType(type: "Collator", optionsBag: .jsIntlCollatorSettings)
54965525
}
54975526

5527+
@discardableResult
5528+
func constructIntlDisplayNames() -> Variable {
5529+
return constructIntlType(type: "DisplayNames", optionsBag: .jsIntlDisplayNamesSettings)
5530+
}
5531+
54985532
@discardableResult
54995533
func constructIntlListFormat() -> Variable {
55005534
return constructIntlType(type: "ListFormat", optionsBag: .jsIntlListFormatSettings)

Sources/Fuzzilli/CodeGen/CodeGenerators.swift

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
import Foundation
16+
1517
// Generator stubs for disposable and async-disposable object variables.
1618
func disposableObjVariableGeneratorStubs(
1719
inContext contextRequirement : Context,
@@ -351,7 +353,47 @@ public let CodeGenerators: [CodeGenerator] = [
351353
},
352354

353355
CodeGenerator("BuiltinIntlGenerator") { b in
354-
let _ = chooseUniform(from: [b.constructIntlDateTimeFormat, b.constructIntlCollator, b.constructIntlListFormat, b.constructIntlLocale, b.constructIntlNumberFormat, b.constructIntlPluralRules, b.constructIntlRelativeTimeFormat, b.constructIntlSegmenter])()
356+
let _ = chooseUniform(from: [
357+
b.constructIntlDateTimeFormat,
358+
b.constructIntlCollator,
359+
b.constructIntlListFormat,
360+
b.constructIntlLocale,
361+
b.constructIntlNumberFormat,
362+
b.constructIntlPluralRules,
363+
b.constructIntlRelativeTimeFormat,
364+
b.constructIntlSegmenter,
365+
b.constructIntlDisplayNames,
366+
{ // Fuzz Intl.DisplayNames.prototype.of()
367+
let intl = b.createNamedVariable(forBuiltin: "Intl")
368+
let ctor = b.getProperty("DisplayNames", of: intl)
369+
let types =
370+
b.fuzzer.environment.getEnum(ofName: "IntlDisplayNamesTypeEnum")!.enumValues
371+
let type = types.randomElement()!
372+
let locale = b.loadString(ProgramBuilder.constructIntlLocaleString())
373+
let options = b.createOptionsBag(.jsIntlDisplayNamesSettings,
374+
predefined: ["type": b.loadString(type)])
375+
b.construct(ctor, withArgs: [locale, options])
376+
let code = switch type {
377+
case "language":
378+
ProgramBuilder.constructIntlLanguageString()
379+
case "region":
380+
ProgramBuilder.constructIntlRegionString()
381+
case "script":
382+
ProgramBuilder.constructIntlScriptString()
383+
case "currency":
384+
Locale.commonISOCurrencyCodes.randomElement()!
385+
case "calendar":
386+
b.fuzzer.environment.getEnum(ofName: "temporalCalendar")!.enumValues
387+
.randomElement()!
388+
case "dateTimeField":
389+
["era", "year", "quarter", "month", "weekOfYear", "weekday", "day",
390+
"dayPeriod", "hour", "minute", "second", "timeZoneName"].randomElement()!
391+
default:
392+
String.random(ofLength: 4)
393+
}
394+
return b.callMethod("of", on: ctor, withArgs: [b.loadString(code)])
395+
}
396+
])()
355397
},
356398

357399
CodeGenerator("HexGenerator") { b in

Sources/Fuzzilli/Environment/JavaScriptEnvironment.swift

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,9 @@ public class JavaScriptEnvironment: ComponentBase {
483483
registerObjectGroup(.jsIntlCollator)
484484
registerObjectGroup(.jsIntlCollatorConstructor)
485485
registerObjectGroup(.jsIntlCollatorPrototype)
486+
registerObjectGroup(.jsIntlDisplayNames)
487+
registerObjectGroup(.jsIntlDisplayNamesConstructor)
488+
registerObjectGroup(.jsIntlDisplayNamesPrototype)
486489
registerObjectGroup(.jsIntlDateTimeFormat)
487490
registerObjectGroup(.jsIntlDateTimeFormatConstructor)
488491
registerObjectGroup(.jsIntlDateTimeFormatPrototype)
@@ -538,6 +541,9 @@ public class JavaScriptEnvironment: ComponentBase {
538541
registerEnumeration(OptionsBag.jsIntlCollationTypeEnum)
539542
registerEnumeration(OptionsBag.jsIntlCaseFirstEnum)
540543
registerEnumeration(OptionsBag.jsIntlCollatorSensitivityEnum)
544+
registerEnumeration(OptionsBag.jsIntlDisplayNamesTypeEnum)
545+
registerEnumeration(OptionsBag.jsIntlDisplayNamesFallbackEnum)
546+
registerEnumeration(OptionsBag.jsIntlDisplayNamesLanguageDisplayEnum)
541547
registerEnumeration(OptionsBag.jsIntlListFormatTypeEnum)
542548
registerEnumeration(OptionsBag.jsIntlNumberFormatStyleEnum)
543549
registerEnumeration(OptionsBag.jsIntlCurrencySystemEnum)
@@ -570,6 +576,7 @@ public class JavaScriptEnvironment: ComponentBase {
570576
registerOptionsBag(.jsTemporalPlainDateToZDTSettings)
571577
registerOptionsBag(.jsIntlDateTimeFormatSettings)
572578
registerOptionsBag(.jsIntlCollatorSettings)
579+
registerOptionsBag(.jsIntlDisplayNamesSettings)
573580
registerOptionsBag(.jsIntlListFormatSettings)
574581
registerOptionsBag(.jsIntlLocaleSettings)
575582
registerOptionsBag(.jsIntlNumberFormatSettings)
@@ -3433,14 +3440,17 @@ extension OptionsBag {
34333440
// Intl
34343441
extension ILType {
34353442
// Intl types
3436-
static let jsIntlObject = ILType.object(ofGroup: "Intl", withProperties: ["DateTimeFormat", "Collator", "ListFormat", "Locale", "NumberFormat", "PluralRules", "RelativeTimeFormat", "Segmenter"], withMethods: ["getCanonicalLocales", "supportedValuesOf"])
3443+
static let jsIntlObject = ILType.object(ofGroup: "Intl", withProperties: ["DateTimeFormat", "Collator", "DisplayNames", "ListFormat", "Locale", "NumberFormat", "PluralRules", "RelativeTimeFormat", "Segmenter"], withMethods: ["getCanonicalLocales", "supportedValuesOf"])
34373444

34383445
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"])
34393446
static let jsIntlLocaleConstructor = ILType.functionAndConstructor([.plain(.jsIntlLocaleString), .opt(OptionsBag.jsIntlLocaleSettings.group.instanceType)] => .jsIntlLocale) + .object(ofGroup: "IntlLocaleConstructor", withProperties: ["prototype"], withMethods: [])
34403447

34413448
static let jsIntlCollator = ILType.object(ofGroup: "Intl.Collator", withProperties: [], withMethods: ["compare", "resolvedOptions"])
34423449
static let jsIntlCollatorConstructor = ILType.functionAndConstructor([.opt(.jsIntlLocaleLike), .opt(OptionsBag.jsIntlCollatorSettings.group.instanceType)] => .jsIntlCollator) + .object(ofGroup: "IntlCollatorConstructor", withProperties: ["prototype"], withMethods: ["supportedLocalesOf"])
34433450

3451+
static let jsIntlDisplayNames = ILType.object(ofGroup: "Intl.DisplayNames", withProperties: [], withMethods: ["of", "resolvedOptions"])
3452+
static let jsIntlDisplayNamesConstructor = ILType.functionAndConstructor([.plain(.jsIntlLocaleLike), .plain(OptionsBag.jsIntlDisplayNamesSettings.group.instanceType)] => .jsIntlDisplayNames) + .object(ofGroup: "IntlDisplayNamesConstructor", withProperties: ["prototype"], withMethods: ["supportedLocalesOf"])
3453+
34443454
static let jsIntlDateTimeFormat = ILType.object(ofGroup: "Intl.DateTimeFormat", withProperties: [], withMethods: ["format", "formatRange", "formatRangeToParts", "formatToParts", "resolvedOptions"])
34453455
static let jsIntlDateTimeFormatConstructor = ILType.functionAndConstructor([.opt(.jsIntlLocaleLike), .opt(OptionsBag.jsIntlDateTimeFormatSettings.group.instanceType)] => .jsIntlDateTimeFormat) + .object(ofGroup: "IntlDateTimeFormatConstructor", withProperties: ["prototype"], withMethods: ["supportedLocalesOf"])
34463456

@@ -3480,6 +3490,7 @@ extension ObjectGroup {
34803490
properties: [
34813491
"Collator" : .jsIntlCollatorConstructor,
34823492
"DateTimeFormat" : .jsIntlDateTimeFormatConstructor,
3493+
"DisplayNames" : .jsIntlDisplayNamesConstructor,
34833494
"ListFormat" : .jsIntlListFormatConstructor,
34843495
"Locale" : .jsIntlLocaleConstructor,
34853496
"NumberFormat" : .jsIntlNumberFormatConstructor,
@@ -3523,6 +3534,33 @@ extension ObjectGroup {
35233534
]
35243535
)
35253536

3537+
static let jsIntlDisplayNames = ObjectGroup(
3538+
name: "Intl.DisplayNames",
3539+
instanceType: .jsIntlDisplayNames,
3540+
properties: [:],
3541+
methods: [
3542+
"of": [.string] => .string, // TODO(mliedtke): The parameter should be typed more precise than string.
3543+
"resolvedOptions": [] => .object(withProperties: ["locale", "style", "type", "fallback", "languageDisplay"]),
3544+
]
3545+
)
3546+
3547+
static let jsIntlDisplayNamesPrototype = createPrototypeObjectGroup(
3548+
jsIntlDisplayNames,
3549+
constructor: .jsIntlDisplayNamesConstructor)
3550+
3551+
static let jsIntlDisplayNamesConstructor = ObjectGroup(
3552+
name: "IntlDisplayNamesConstructor",
3553+
constructorPath: "Intl.DisplayNames",
3554+
instanceType: .jsIntlDisplayNamesConstructor,
3555+
properties: [
3556+
"prototype" : jsIntlDisplayNamesPrototype.instanceType
3557+
],
3558+
methods: [
3559+
// TODO(manishearth) this also accepts arrays of locale-likes
3560+
"supportedLocalesOf": [.opt(.jsIntlLocaleLike), .opt(OptionsBag.jsIntlLocaleMatcherSettings.group.instanceType)] => .jsArray,
3561+
]
3562+
)
3563+
35263564
fileprivate static func dateTimeFormatSignature(_ returnType: ILType) -> [Signature] {
35273565
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/format#date
35283566
// No ZonedDateTime as stated in the docs.
@@ -3799,6 +3837,9 @@ extension OptionsBag {
37993837
fileprivate static let jsIntlCollationTypeEnum = ILType.enumeration(ofName: "IntlCollationType", withValues: ["compat", "emoji", "eor", "phonebk", "pinyin", "searchjl", "stroke", "trad", "unihan", "zhuyin"])
38003838
fileprivate static let jsIntlCaseFirstEnum = ILType.enumeration(ofName: "IntlCaseFirst", withValues: ["upper", "lower", "false"])
38013839
fileprivate static let jsIntlCollatorSensitivityEnum = ILType.enumeration(ofName: "IntlCollatorSensitivity", withValues: ["base", "accent", "case", "variant"])
3840+
fileprivate static let jsIntlDisplayNamesTypeEnum = ILType.enumeration(ofName: "IntlDisplayNamesTypeEnum", withValues: ["language", "region", "script", "currency", "calendar", "dateTimeField"])
3841+
fileprivate static let jsIntlDisplayNamesFallbackEnum = ILType.enumeration(ofName: "IntlDisplayNamesFallbackEnum", withValues: ["code", "none"])
3842+
fileprivate static let jsIntlDisplayNamesLanguageDisplayEnum = ILType.enumeration(ofName: "IntlDisplayNamesLanguageDisplayEnum", withValues: ["dialect", "standard"])
38023843
fileprivate static let jsIntlListFormatTypeEnum = ILType.enumeration(ofName: "IntlListFormatTypeEnum", withValues: ["conjunction", "disjunction", "unit"])
38033844
fileprivate static let jsIntlNumberFormatStyleEnum = ILType.enumeration(ofName: "IntlNumberFormatStyleEnum", withValues: ["decimal", "currency", "percent", "unit"])
38043845
fileprivate static let jsIntlCurrencySystemEnum = ILType.enumeration(ofName: "IntlCurrency", withValues: Locale.Currency.isoCurrencies.map { $0.identifier })
@@ -3857,6 +3898,18 @@ extension OptionsBag {
38573898
]
38583899
)
38593900

3901+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DisplayNames/DisplayNames#options
3902+
static let jsIntlDisplayNamesSettings = OptionsBag(
3903+
name: "IntlDisplayNamesSettings",
3904+
properties: [
3905+
"localeMatcher": jsIntlLocaleMatcherEnum,
3906+
"style": jsIntlLongShortNarrowEnum,
3907+
"type": jsIntlDisplayNamesTypeEnum,
3908+
"fallback": jsIntlDisplayNamesFallbackEnum,
3909+
"languageDisplay": jsIntlDisplayNamesLanguageDisplayEnum,
3910+
]
3911+
)
3912+
38603913
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/ListFormat#options
38613914
static let jsIntlListFormatSettings = OptionsBag(
38623915
name: "IntlListFormatSettings",

0 commit comments

Comments
 (0)