forked from rpms/glibc
Compare commits
No commits in common. "c8" and "c9-beta" have entirely different histories.
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1 @@
|
|||||||
SOURCES/glibc-2.28.tar.xz
|
SOURCES/glibc-2.34.tar.xz
|
||||||
|
@ -1 +1 @@
|
|||||||
ccb5dc9e51a9884df8488f86982439d47b283b2a SOURCES/glibc-2.28.tar.xz
|
7c3b8890a6346793b6334cc5f2fea5d437d307b8 SOURCES/glibc-2.34.tar.xz
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,495 +0,0 @@
|
|||||||
# This file names the currently supported and somewhat tested locales.
|
|
||||||
# If you have any additions please file a glibc bug report.
|
|
||||||
SUPPORTED-LOCALES=\
|
|
||||||
C.UTF-8/UTF-8 \
|
|
||||||
aa_DJ.UTF-8/UTF-8 \
|
|
||||||
aa_DJ/ISO-8859-1 \
|
|
||||||
aa_ER/UTF-8 \
|
|
||||||
aa_ER@saaho/UTF-8 \
|
|
||||||
aa_ET/UTF-8 \
|
|
||||||
af_ZA.UTF-8/UTF-8 \
|
|
||||||
af_ZA/ISO-8859-1 \
|
|
||||||
agr_PE/UTF-8 \
|
|
||||||
ak_GH/UTF-8 \
|
|
||||||
am_ET/UTF-8 \
|
|
||||||
an_ES.UTF-8/UTF-8 \
|
|
||||||
an_ES/ISO-8859-15 \
|
|
||||||
anp_IN/UTF-8 \
|
|
||||||
ar_AE.UTF-8/UTF-8 \
|
|
||||||
ar_AE/ISO-8859-6 \
|
|
||||||
ar_BH.UTF-8/UTF-8 \
|
|
||||||
ar_BH/ISO-8859-6 \
|
|
||||||
ar_DZ.UTF-8/UTF-8 \
|
|
||||||
ar_DZ/ISO-8859-6 \
|
|
||||||
ar_EG.UTF-8/UTF-8 \
|
|
||||||
ar_EG/ISO-8859-6 \
|
|
||||||
ar_IN/UTF-8 \
|
|
||||||
ar_IQ.UTF-8/UTF-8 \
|
|
||||||
ar_IQ/ISO-8859-6 \
|
|
||||||
ar_JO.UTF-8/UTF-8 \
|
|
||||||
ar_JO/ISO-8859-6 \
|
|
||||||
ar_KW.UTF-8/UTF-8 \
|
|
||||||
ar_KW/ISO-8859-6 \
|
|
||||||
ar_LB.UTF-8/UTF-8 \
|
|
||||||
ar_LB/ISO-8859-6 \
|
|
||||||
ar_LY.UTF-8/UTF-8 \
|
|
||||||
ar_LY/ISO-8859-6 \
|
|
||||||
ar_MA.UTF-8/UTF-8 \
|
|
||||||
ar_MA/ISO-8859-6 \
|
|
||||||
ar_OM.UTF-8/UTF-8 \
|
|
||||||
ar_OM/ISO-8859-6 \
|
|
||||||
ar_QA.UTF-8/UTF-8 \
|
|
||||||
ar_QA/ISO-8859-6 \
|
|
||||||
ar_SA.UTF-8/UTF-8 \
|
|
||||||
ar_SA/ISO-8859-6 \
|
|
||||||
ar_SD.UTF-8/UTF-8 \
|
|
||||||
ar_SD/ISO-8859-6 \
|
|
||||||
ar_SS/UTF-8 \
|
|
||||||
ar_SY.UTF-8/UTF-8 \
|
|
||||||
ar_SY/ISO-8859-6 \
|
|
||||||
ar_TN.UTF-8/UTF-8 \
|
|
||||||
ar_TN/ISO-8859-6 \
|
|
||||||
ar_YE.UTF-8/UTF-8 \
|
|
||||||
ar_YE/ISO-8859-6 \
|
|
||||||
ayc_PE/UTF-8 \
|
|
||||||
az_AZ/UTF-8 \
|
|
||||||
az_IR/UTF-8 \
|
|
||||||
as_IN/UTF-8 \
|
|
||||||
ast_ES.UTF-8/UTF-8 \
|
|
||||||
ast_ES/ISO-8859-15 \
|
|
||||||
be_BY.UTF-8/UTF-8 \
|
|
||||||
be_BY/CP1251 \
|
|
||||||
be_BY@latin/UTF-8 \
|
|
||||||
bem_ZM/UTF-8 \
|
|
||||||
ber_DZ/UTF-8 \
|
|
||||||
ber_MA/UTF-8 \
|
|
||||||
bg_BG.UTF-8/UTF-8 \
|
|
||||||
bg_BG/CP1251 \
|
|
||||||
bhb_IN.UTF-8/UTF-8 \
|
|
||||||
bho_IN/UTF-8 \
|
|
||||||
bho_NP/UTF-8 \
|
|
||||||
bi_VU/UTF-8 \
|
|
||||||
bn_BD/UTF-8 \
|
|
||||||
bn_IN/UTF-8 \
|
|
||||||
bo_CN/UTF-8 \
|
|
||||||
bo_IN/UTF-8 \
|
|
||||||
br_FR.UTF-8/UTF-8 \
|
|
||||||
br_FR/ISO-8859-1 \
|
|
||||||
br_FR@euro/ISO-8859-15 \
|
|
||||||
brx_IN/UTF-8 \
|
|
||||||
bs_BA.UTF-8/UTF-8 \
|
|
||||||
bs_BA/ISO-8859-2 \
|
|
||||||
byn_ER/UTF-8 \
|
|
||||||
ca_AD.UTF-8/UTF-8 \
|
|
||||||
ca_AD/ISO-8859-15 \
|
|
||||||
ca_ES.UTF-8/UTF-8 \
|
|
||||||
ca_ES/ISO-8859-1 \
|
|
||||||
ca_ES@euro/ISO-8859-15 \
|
|
||||||
ca_ES@valencia/UTF-8 \
|
|
||||||
ca_FR.UTF-8/UTF-8 \
|
|
||||||
ca_FR/ISO-8859-15 \
|
|
||||||
ca_IT.UTF-8/UTF-8 \
|
|
||||||
ca_IT/ISO-8859-15 \
|
|
||||||
ce_RU/UTF-8 \
|
|
||||||
chr_US/UTF-8 \
|
|
||||||
cmn_TW/UTF-8 \
|
|
||||||
crh_UA/UTF-8 \
|
|
||||||
cs_CZ.UTF-8/UTF-8 \
|
|
||||||
cs_CZ/ISO-8859-2 \
|
|
||||||
csb_PL/UTF-8 \
|
|
||||||
cv_RU/UTF-8 \
|
|
||||||
cy_GB.UTF-8/UTF-8 \
|
|
||||||
cy_GB/ISO-8859-14 \
|
|
||||||
da_DK.UTF-8/UTF-8 \
|
|
||||||
da_DK/ISO-8859-1 \
|
|
||||||
da_DK.ISO-8859-15/ISO-8859-15 \
|
|
||||||
de_AT.UTF-8/UTF-8 \
|
|
||||||
de_AT/ISO-8859-1 \
|
|
||||||
de_AT@euro/ISO-8859-15 \
|
|
||||||
de_BE.UTF-8/UTF-8 \
|
|
||||||
de_BE/ISO-8859-1 \
|
|
||||||
de_BE@euro/ISO-8859-15 \
|
|
||||||
de_CH.UTF-8/UTF-8 \
|
|
||||||
de_CH/ISO-8859-1 \
|
|
||||||
de_DE.UTF-8/UTF-8 \
|
|
||||||
de_DE/ISO-8859-1 \
|
|
||||||
de_DE@euro/ISO-8859-15 \
|
|
||||||
de_IT.UTF-8/UTF-8 \
|
|
||||||
de_IT/ISO-8859-1 \
|
|
||||||
de_LI.UTF-8/UTF-8 \
|
|
||||||
de_LU.UTF-8/UTF-8 \
|
|
||||||
de_LU/ISO-8859-1 \
|
|
||||||
de_LU@euro/ISO-8859-15 \
|
|
||||||
doi_IN/UTF-8 \
|
|
||||||
dsb_DE/UTF-8 \
|
|
||||||
dv_MV/UTF-8 \
|
|
||||||
dz_BT/UTF-8 \
|
|
||||||
el_GR.UTF-8/UTF-8 \
|
|
||||||
el_GR/ISO-8859-7 \
|
|
||||||
el_GR@euro/ISO-8859-7 \
|
|
||||||
el_CY.UTF-8/UTF-8 \
|
|
||||||
el_CY/ISO-8859-7 \
|
|
||||||
en_AG/UTF-8 \
|
|
||||||
en_AU.UTF-8/UTF-8 \
|
|
||||||
en_AU/ISO-8859-1 \
|
|
||||||
en_BW.UTF-8/UTF-8 \
|
|
||||||
en_BW/ISO-8859-1 \
|
|
||||||
en_CA.UTF-8/UTF-8 \
|
|
||||||
en_CA/ISO-8859-1 \
|
|
||||||
en_DK.UTF-8/UTF-8 \
|
|
||||||
en_DK/ISO-8859-1 \
|
|
||||||
en_GB.UTF-8/UTF-8 \
|
|
||||||
en_GB/ISO-8859-1 \
|
|
||||||
en_GB.ISO-8859-15/ISO-8859-15 \
|
|
||||||
en_HK.UTF-8/UTF-8 \
|
|
||||||
en_HK/ISO-8859-1 \
|
|
||||||
en_IE.UTF-8/UTF-8 \
|
|
||||||
en_IE/ISO-8859-1 \
|
|
||||||
en_IE@euro/ISO-8859-15 \
|
|
||||||
en_IL/UTF-8 \
|
|
||||||
en_IN/UTF-8 \
|
|
||||||
en_NG/UTF-8 \
|
|
||||||
en_NZ.UTF-8/UTF-8 \
|
|
||||||
en_NZ/ISO-8859-1 \
|
|
||||||
en_PH.UTF-8/UTF-8 \
|
|
||||||
en_PH/ISO-8859-1 \
|
|
||||||
en_SC.UTF-8/UTF-8 \
|
|
||||||
en_SG.UTF-8/UTF-8 \
|
|
||||||
en_SG/ISO-8859-1 \
|
|
||||||
en_US.UTF-8/UTF-8 \
|
|
||||||
en_US/ISO-8859-1 \
|
|
||||||
en_US.ISO-8859-15/ISO-8859-15 \
|
|
||||||
en_US@ampm.UTF-8/UTF-8 \
|
|
||||||
en_ZA.UTF-8/UTF-8 \
|
|
||||||
en_ZA/ISO-8859-1 \
|
|
||||||
en_ZM/UTF-8 \
|
|
||||||
en_ZW.UTF-8/UTF-8 \
|
|
||||||
en_ZW/ISO-8859-1 \
|
|
||||||
eo/UTF-8 \
|
|
||||||
es_AR.UTF-8/UTF-8 \
|
|
||||||
es_AR/ISO-8859-1 \
|
|
||||||
es_BO.UTF-8/UTF-8 \
|
|
||||||
es_BO/ISO-8859-1 \
|
|
||||||
es_CL.UTF-8/UTF-8 \
|
|
||||||
es_CL/ISO-8859-1 \
|
|
||||||
es_CO.UTF-8/UTF-8 \
|
|
||||||
es_CO/ISO-8859-1 \
|
|
||||||
es_CR.UTF-8/UTF-8 \
|
|
||||||
es_CR/ISO-8859-1 \
|
|
||||||
es_CU/UTF-8 \
|
|
||||||
es_DO.UTF-8/UTF-8 \
|
|
||||||
es_DO/ISO-8859-1 \
|
|
||||||
es_EC.UTF-8/UTF-8 \
|
|
||||||
es_EC/ISO-8859-1 \
|
|
||||||
es_ES.UTF-8/UTF-8 \
|
|
||||||
es_ES/ISO-8859-1 \
|
|
||||||
es_ES@euro/ISO-8859-15 \
|
|
||||||
es_GT.UTF-8/UTF-8 \
|
|
||||||
es_GT/ISO-8859-1 \
|
|
||||||
es_HN.UTF-8/UTF-8 \
|
|
||||||
es_HN/ISO-8859-1 \
|
|
||||||
es_MX.UTF-8/UTF-8 \
|
|
||||||
es_MX/ISO-8859-1 \
|
|
||||||
es_NI.UTF-8/UTF-8 \
|
|
||||||
es_NI/ISO-8859-1 \
|
|
||||||
es_PA.UTF-8/UTF-8 \
|
|
||||||
es_PA/ISO-8859-1 \
|
|
||||||
es_PE.UTF-8/UTF-8 \
|
|
||||||
es_PE/ISO-8859-1 \
|
|
||||||
es_PR.UTF-8/UTF-8 \
|
|
||||||
es_PR/ISO-8859-1 \
|
|
||||||
es_PY.UTF-8/UTF-8 \
|
|
||||||
es_PY/ISO-8859-1 \
|
|
||||||
es_SV.UTF-8/UTF-8 \
|
|
||||||
es_SV/ISO-8859-1 \
|
|
||||||
es_US.UTF-8/UTF-8 \
|
|
||||||
es_US/ISO-8859-1 \
|
|
||||||
es_UY.UTF-8/UTF-8 \
|
|
||||||
es_UY/ISO-8859-1 \
|
|
||||||
es_VE.UTF-8/UTF-8 \
|
|
||||||
es_VE/ISO-8859-1 \
|
|
||||||
et_EE.UTF-8/UTF-8 \
|
|
||||||
et_EE/ISO-8859-1 \
|
|
||||||
et_EE.ISO-8859-15/ISO-8859-15 \
|
|
||||||
eu_ES.UTF-8/UTF-8 \
|
|
||||||
eu_ES/ISO-8859-1 \
|
|
||||||
eu_ES@euro/ISO-8859-15 \
|
|
||||||
fa_IR/UTF-8 \
|
|
||||||
ff_SN/UTF-8 \
|
|
||||||
fi_FI.UTF-8/UTF-8 \
|
|
||||||
fi_FI/ISO-8859-1 \
|
|
||||||
fi_FI@euro/ISO-8859-15 \
|
|
||||||
fil_PH/UTF-8 \
|
|
||||||
fo_FO.UTF-8/UTF-8 \
|
|
||||||
fo_FO/ISO-8859-1 \
|
|
||||||
fr_BE.UTF-8/UTF-8 \
|
|
||||||
fr_BE/ISO-8859-1 \
|
|
||||||
fr_BE@euro/ISO-8859-15 \
|
|
||||||
fr_CA.UTF-8/UTF-8 \
|
|
||||||
fr_CA/ISO-8859-1 \
|
|
||||||
fr_CH.UTF-8/UTF-8 \
|
|
||||||
fr_CH/ISO-8859-1 \
|
|
||||||
fr_FR.UTF-8/UTF-8 \
|
|
||||||
fr_FR/ISO-8859-1 \
|
|
||||||
fr_FR@euro/ISO-8859-15 \
|
|
||||||
fr_LU.UTF-8/UTF-8 \
|
|
||||||
fr_LU/ISO-8859-1 \
|
|
||||||
fr_LU@euro/ISO-8859-15 \
|
|
||||||
fur_IT/UTF-8 \
|
|
||||||
fy_NL/UTF-8 \
|
|
||||||
fy_DE/UTF-8 \
|
|
||||||
ga_IE.UTF-8/UTF-8 \
|
|
||||||
ga_IE/ISO-8859-1 \
|
|
||||||
ga_IE@euro/ISO-8859-15 \
|
|
||||||
gd_GB.UTF-8/UTF-8 \
|
|
||||||
gd_GB/ISO-8859-15 \
|
|
||||||
gez_ER/UTF-8 \
|
|
||||||
gez_ER@abegede/UTF-8 \
|
|
||||||
gez_ET/UTF-8 \
|
|
||||||
gez_ET@abegede/UTF-8 \
|
|
||||||
gl_ES.UTF-8/UTF-8 \
|
|
||||||
gl_ES/ISO-8859-1 \
|
|
||||||
gl_ES@euro/ISO-8859-15 \
|
|
||||||
gu_IN/UTF-8 \
|
|
||||||
gv_GB.UTF-8/UTF-8 \
|
|
||||||
gv_GB/ISO-8859-1 \
|
|
||||||
ha_NG/UTF-8 \
|
|
||||||
hak_TW/UTF-8 \
|
|
||||||
he_IL.UTF-8/UTF-8 \
|
|
||||||
he_IL/ISO-8859-8 \
|
|
||||||
hi_IN/UTF-8 \
|
|
||||||
hif_FJ/UTF-8 \
|
|
||||||
hne_IN/UTF-8 \
|
|
||||||
hr_HR.UTF-8/UTF-8 \
|
|
||||||
hr_HR/ISO-8859-2 \
|
|
||||||
hsb_DE/ISO-8859-2 \
|
|
||||||
hsb_DE.UTF-8/UTF-8 \
|
|
||||||
ht_HT/UTF-8 \
|
|
||||||
hu_HU.UTF-8/UTF-8 \
|
|
||||||
hu_HU/ISO-8859-2 \
|
|
||||||
hy_AM/UTF-8 \
|
|
||||||
hy_AM.ARMSCII-8/ARMSCII-8 \
|
|
||||||
ia_FR/UTF-8 \
|
|
||||||
id_ID.UTF-8/UTF-8 \
|
|
||||||
id_ID/ISO-8859-1 \
|
|
||||||
ig_NG/UTF-8 \
|
|
||||||
ik_CA/UTF-8 \
|
|
||||||
is_IS.UTF-8/UTF-8 \
|
|
||||||
is_IS/ISO-8859-1 \
|
|
||||||
it_CH.UTF-8/UTF-8 \
|
|
||||||
it_CH/ISO-8859-1 \
|
|
||||||
it_IT.UTF-8/UTF-8 \
|
|
||||||
it_IT/ISO-8859-1 \
|
|
||||||
it_IT@euro/ISO-8859-15 \
|
|
||||||
iu_CA/UTF-8 \
|
|
||||||
ja_JP.EUC-JP/EUC-JP \
|
|
||||||
ja_JP.UTF-8/UTF-8 \
|
|
||||||
ka_GE.UTF-8/UTF-8 \
|
|
||||||
ka_GE/GEORGIAN-PS \
|
|
||||||
kab_DZ/UTF-8 \
|
|
||||||
kk_KZ.UTF-8/UTF-8 \
|
|
||||||
kk_KZ/PT154 \
|
|
||||||
kl_GL.UTF-8/UTF-8 \
|
|
||||||
kl_GL/ISO-8859-1 \
|
|
||||||
km_KH/UTF-8 \
|
|
||||||
kn_IN/UTF-8 \
|
|
||||||
ko_KR.EUC-KR/EUC-KR \
|
|
||||||
ko_KR.UTF-8/UTF-8 \
|
|
||||||
kok_IN/UTF-8 \
|
|
||||||
ks_IN/UTF-8 \
|
|
||||||
ks_IN@devanagari/UTF-8 \
|
|
||||||
ku_TR.UTF-8/UTF-8 \
|
|
||||||
ku_TR/ISO-8859-9 \
|
|
||||||
kw_GB.UTF-8/UTF-8 \
|
|
||||||
kw_GB/ISO-8859-1 \
|
|
||||||
ky_KG/UTF-8 \
|
|
||||||
lb_LU/UTF-8 \
|
|
||||||
lg_UG.UTF-8/UTF-8 \
|
|
||||||
lg_UG/ISO-8859-10 \
|
|
||||||
li_BE/UTF-8 \
|
|
||||||
li_NL/UTF-8 \
|
|
||||||
lij_IT/UTF-8 \
|
|
||||||
ln_CD/UTF-8 \
|
|
||||||
lo_LA/UTF-8 \
|
|
||||||
lt_LT.UTF-8/UTF-8 \
|
|
||||||
lt_LT/ISO-8859-13 \
|
|
||||||
lv_LV.UTF-8/UTF-8 \
|
|
||||||
lv_LV/ISO-8859-13 \
|
|
||||||
lzh_TW/UTF-8 \
|
|
||||||
mag_IN/UTF-8 \
|
|
||||||
mai_IN/UTF-8 \
|
|
||||||
mai_NP/UTF-8 \
|
|
||||||
mfe_MU/UTF-8 \
|
|
||||||
mg_MG.UTF-8/UTF-8 \
|
|
||||||
mg_MG/ISO-8859-15 \
|
|
||||||
mhr_RU/UTF-8 \
|
|
||||||
mi_NZ.UTF-8/UTF-8 \
|
|
||||||
mi_NZ/ISO-8859-13 \
|
|
||||||
miq_NI/UTF-8 \
|
|
||||||
mjw_IN/UTF-8 \
|
|
||||||
mk_MK.UTF-8/UTF-8 \
|
|
||||||
mk_MK/ISO-8859-5 \
|
|
||||||
ml_IN/UTF-8 \
|
|
||||||
mn_MN/UTF-8 \
|
|
||||||
mni_IN/UTF-8 \
|
|
||||||
mr_IN/UTF-8 \
|
|
||||||
ms_MY.UTF-8/UTF-8 \
|
|
||||||
ms_MY/ISO-8859-1 \
|
|
||||||
mt_MT.UTF-8/UTF-8 \
|
|
||||||
mt_MT/ISO-8859-3 \
|
|
||||||
my_MM/UTF-8 \
|
|
||||||
nan_TW/UTF-8 \
|
|
||||||
nan_TW@latin/UTF-8 \
|
|
||||||
nb_NO.UTF-8/UTF-8 \
|
|
||||||
nb_NO/ISO-8859-1 \
|
|
||||||
nds_DE/UTF-8 \
|
|
||||||
nds_NL/UTF-8 \
|
|
||||||
ne_NP/UTF-8 \
|
|
||||||
nhn_MX/UTF-8 \
|
|
||||||
niu_NU/UTF-8 \
|
|
||||||
niu_NZ/UTF-8 \
|
|
||||||
nl_AW/UTF-8 \
|
|
||||||
nl_BE.UTF-8/UTF-8 \
|
|
||||||
nl_BE/ISO-8859-1 \
|
|
||||||
nl_BE@euro/ISO-8859-15 \
|
|
||||||
nl_NL.UTF-8/UTF-8 \
|
|
||||||
nl_NL/ISO-8859-1 \
|
|
||||||
nl_NL@euro/ISO-8859-15 \
|
|
||||||
nn_NO.UTF-8/UTF-8 \
|
|
||||||
nn_NO/ISO-8859-1 \
|
|
||||||
nr_ZA/UTF-8 \
|
|
||||||
nso_ZA/UTF-8 \
|
|
||||||
oc_FR.UTF-8/UTF-8 \
|
|
||||||
oc_FR/ISO-8859-1 \
|
|
||||||
om_ET/UTF-8 \
|
|
||||||
om_KE.UTF-8/UTF-8 \
|
|
||||||
om_KE/ISO-8859-1 \
|
|
||||||
or_IN/UTF-8 \
|
|
||||||
os_RU/UTF-8 \
|
|
||||||
pa_IN/UTF-8 \
|
|
||||||
pa_PK/UTF-8 \
|
|
||||||
pap_AW/UTF-8 \
|
|
||||||
pap_CW/UTF-8 \
|
|
||||||
pl_PL.UTF-8/UTF-8 \
|
|
||||||
pl_PL/ISO-8859-2 \
|
|
||||||
ps_AF/UTF-8 \
|
|
||||||
pt_BR.UTF-8/UTF-8 \
|
|
||||||
pt_BR/ISO-8859-1 \
|
|
||||||
pt_PT.UTF-8/UTF-8 \
|
|
||||||
pt_PT/ISO-8859-1 \
|
|
||||||
pt_PT@euro/ISO-8859-15 \
|
|
||||||
quz_PE/UTF-8 \
|
|
||||||
raj_IN/UTF-8 \
|
|
||||||
ro_RO.UTF-8/UTF-8 \
|
|
||||||
ro_RO/ISO-8859-2 \
|
|
||||||
ru_RU.KOI8-R/KOI8-R \
|
|
||||||
ru_RU.UTF-8/UTF-8 \
|
|
||||||
ru_RU/ISO-8859-5 \
|
|
||||||
ru_UA.UTF-8/UTF-8 \
|
|
||||||
ru_UA/KOI8-U \
|
|
||||||
rw_RW/UTF-8 \
|
|
||||||
sa_IN/UTF-8 \
|
|
||||||
sah_RU/UTF-8 \
|
|
||||||
sat_IN/UTF-8 \
|
|
||||||
sc_IT/UTF-8 \
|
|
||||||
sd_IN/UTF-8 \
|
|
||||||
sd_IN@devanagari/UTF-8 \
|
|
||||||
se_NO/UTF-8 \
|
|
||||||
sgs_LT/UTF-8 \
|
|
||||||
shn_MM/UTF-8 \
|
|
||||||
shs_CA/UTF-8 \
|
|
||||||
si_LK/UTF-8 \
|
|
||||||
sid_ET/UTF-8 \
|
|
||||||
sk_SK.UTF-8/UTF-8 \
|
|
||||||
sk_SK/ISO-8859-2 \
|
|
||||||
sl_SI.UTF-8/UTF-8 \
|
|
||||||
sl_SI/ISO-8859-2 \
|
|
||||||
sm_WS/UTF-8 \
|
|
||||||
so_DJ.UTF-8/UTF-8 \
|
|
||||||
so_DJ/ISO-8859-1 \
|
|
||||||
so_ET/UTF-8 \
|
|
||||||
so_KE.UTF-8/UTF-8 \
|
|
||||||
so_KE/ISO-8859-1 \
|
|
||||||
so_SO.UTF-8/UTF-8 \
|
|
||||||
so_SO/ISO-8859-1 \
|
|
||||||
sq_AL.UTF-8/UTF-8 \
|
|
||||||
sq_AL/ISO-8859-1 \
|
|
||||||
sq_MK/UTF-8 \
|
|
||||||
sr_ME/UTF-8 \
|
|
||||||
sr_RS/UTF-8 \
|
|
||||||
sr_RS@latin/UTF-8 \
|
|
||||||
ss_ZA/UTF-8 \
|
|
||||||
st_ZA.UTF-8/UTF-8 \
|
|
||||||
st_ZA/ISO-8859-1 \
|
|
||||||
sv_FI.UTF-8/UTF-8 \
|
|
||||||
sv_FI/ISO-8859-1 \
|
|
||||||
sv_FI@euro/ISO-8859-15 \
|
|
||||||
sv_SE.UTF-8/UTF-8 \
|
|
||||||
sv_SE/ISO-8859-1 \
|
|
||||||
sv_SE.ISO-8859-15/ISO-8859-15 \
|
|
||||||
sw_KE/UTF-8 \
|
|
||||||
sw_TZ/UTF-8 \
|
|
||||||
szl_PL/UTF-8 \
|
|
||||||
ta_IN/UTF-8 \
|
|
||||||
ta_LK/UTF-8 \
|
|
||||||
tcy_IN.UTF-8/UTF-8 \
|
|
||||||
te_IN/UTF-8 \
|
|
||||||
tg_TJ.UTF-8/UTF-8 \
|
|
||||||
tg_TJ/KOI8-T \
|
|
||||||
th_TH.UTF-8/UTF-8 \
|
|
||||||
th_TH/TIS-620 \
|
|
||||||
the_NP/UTF-8 \
|
|
||||||
ti_ER/UTF-8 \
|
|
||||||
ti_ET/UTF-8 \
|
|
||||||
tig_ER/UTF-8 \
|
|
||||||
tk_TM/UTF-8 \
|
|
||||||
tl_PH.UTF-8/UTF-8 \
|
|
||||||
tl_PH/ISO-8859-1 \
|
|
||||||
tn_ZA/UTF-8 \
|
|
||||||
to_TO/UTF-8 \
|
|
||||||
tpi_PG/UTF-8 \
|
|
||||||
tr_CY.UTF-8/UTF-8 \
|
|
||||||
tr_CY/ISO-8859-9 \
|
|
||||||
tr_TR.UTF-8/UTF-8 \
|
|
||||||
tr_TR/ISO-8859-9 \
|
|
||||||
ts_ZA/UTF-8 \
|
|
||||||
tt_RU/UTF-8 \
|
|
||||||
tt_RU@iqtelif/UTF-8 \
|
|
||||||
ug_CN/UTF-8 \
|
|
||||||
uk_UA.UTF-8/UTF-8 \
|
|
||||||
uk_UA/KOI8-U \
|
|
||||||
unm_US/UTF-8 \
|
|
||||||
ur_IN/UTF-8 \
|
|
||||||
ur_PK/UTF-8 \
|
|
||||||
uz_UZ.UTF-8/UTF-8 \
|
|
||||||
uz_UZ/ISO-8859-1 \
|
|
||||||
uz_UZ@cyrillic/UTF-8 \
|
|
||||||
ve_ZA/UTF-8 \
|
|
||||||
vi_VN/UTF-8 \
|
|
||||||
wa_BE/ISO-8859-1 \
|
|
||||||
wa_BE@euro/ISO-8859-15 \
|
|
||||||
wa_BE.UTF-8/UTF-8 \
|
|
||||||
wae_CH/UTF-8 \
|
|
||||||
wal_ET/UTF-8 \
|
|
||||||
wo_SN/UTF-8 \
|
|
||||||
xh_ZA.UTF-8/UTF-8 \
|
|
||||||
xh_ZA/ISO-8859-1 \
|
|
||||||
yi_US.UTF-8/UTF-8 \
|
|
||||||
yi_US/CP1255 \
|
|
||||||
yo_NG/UTF-8 \
|
|
||||||
yue_HK/UTF-8 \
|
|
||||||
yuw_PG/UTF-8 \
|
|
||||||
zh_CN.GB18030/GB18030 \
|
|
||||||
zh_CN.GBK/GBK \
|
|
||||||
zh_CN.UTF-8/UTF-8 \
|
|
||||||
zh_CN/GB2312 \
|
|
||||||
zh_HK.UTF-8/UTF-8 \
|
|
||||||
zh_HK/BIG5-HKSCS \
|
|
||||||
zh_SG.UTF-8/UTF-8 \
|
|
||||||
zh_SG.GBK/GBK \
|
|
||||||
zh_SG/GB2312 \
|
|
||||||
zh_TW.EUC-TW/EUC-TW \
|
|
||||||
zh_TW.UTF-8/UTF-8 \
|
|
||||||
zh_TW/BIG5 \
|
|
||||||
zu_ZA.UTF-8/UTF-8 \
|
|
||||||
zu_ZA/ISO-8859-1 \
|
|
@ -1,862 +0,0 @@
|
|||||||
#define _GNU_SOURCE
|
|
||||||
#include <assert.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <locale.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "../locale/hashval.h"
|
|
||||||
#define __LC_LAST 13
|
|
||||||
#include "../locale/locarchive.h"
|
|
||||||
#include "../crypt/md5.h"
|
|
||||||
|
|
||||||
const char *alias_file = DATADIR "/locale/locale.alias";
|
|
||||||
const char *locar_file = PREFIX "/lib/locale/locale-archive";
|
|
||||||
const char *tmpl_file = PREFIX "/lib/locale/locale-archive.tmpl";
|
|
||||||
const char *loc_path = PREFIX "/lib/locale/";
|
|
||||||
/* Flags set by `--verbose` option. */
|
|
||||||
int be_quiet = 1;
|
|
||||||
int verbose = 0;
|
|
||||||
int max_locarchive_open_retry = 10;
|
|
||||||
const char *output_prefix;
|
|
||||||
|
|
||||||
/* Endianness should have been taken care of by localedef. We don't need to do
|
|
||||||
additional swapping. We need this variable exported however, since
|
|
||||||
locarchive.c uses it to determine if it needs to swap endianness of a value
|
|
||||||
before writing to or reading from the archive. */
|
|
||||||
bool swap_endianness_p = false;
|
|
||||||
|
|
||||||
static const char *locnames[] =
|
|
||||||
{
|
|
||||||
#define DEFINE_CATEGORY(category, category_name, items, a) \
|
|
||||||
[category] = category_name,
|
|
||||||
#include "../locale/categories.def"
|
|
||||||
#undef DEFINE_CATEGORY
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
is_prime (unsigned long candidate)
|
|
||||||
{
|
|
||||||
/* No even number and none less than 10 will be passed here. */
|
|
||||||
unsigned long int divn = 3;
|
|
||||||
unsigned long int sq = divn * divn;
|
|
||||||
|
|
||||||
while (sq < candidate && candidate % divn != 0)
|
|
||||||
{
|
|
||||||
++divn;
|
|
||||||
sq += 4 * divn;
|
|
||||||
++divn;
|
|
||||||
}
|
|
||||||
|
|
||||||
return candidate % divn != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long
|
|
||||||
next_prime (unsigned long seed)
|
|
||||||
{
|
|
||||||
/* Make it definitely odd. */
|
|
||||||
seed |= 1;
|
|
||||||
|
|
||||||
while (!is_prime (seed))
|
|
||||||
seed += 2;
|
|
||||||
|
|
||||||
return seed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
error (int status, int errnum, const char *message, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
|
|
||||||
va_start (args, message);
|
|
||||||
fflush (stdout);
|
|
||||||
fprintf (stderr, "%s: ", program_invocation_name);
|
|
||||||
vfprintf (stderr, message, args);
|
|
||||||
va_end (args);
|
|
||||||
if (errnum)
|
|
||||||
fprintf (stderr, ": %s", strerror (errnum));
|
|
||||||
putc ('\n', stderr);
|
|
||||||
fflush (stderr);
|
|
||||||
if (status)
|
|
||||||
exit (errnum == EROFS ? 0 : status);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
xmalloc (size_t size)
|
|
||||||
{
|
|
||||||
void *p = malloc (size);
|
|
||||||
if (p == NULL)
|
|
||||||
error (EXIT_FAILURE, errno, "could not allocate %zd bytes of memory", size);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
open_tmpl_archive (struct locarhandle *ah)
|
|
||||||
{
|
|
||||||
struct stat64 st;
|
|
||||||
int fd;
|
|
||||||
struct locarhead head;
|
|
||||||
const char *archivefname = ah->fname == NULL ? tmpl_file : ah->fname;
|
|
||||||
|
|
||||||
/* Open the archive. We must have exclusive write access. */
|
|
||||||
fd = open64 (archivefname, O_RDONLY);
|
|
||||||
if (fd == -1)
|
|
||||||
error (EXIT_FAILURE, errno, "cannot open locale archive template file \"%s\"",
|
|
||||||
archivefname);
|
|
||||||
|
|
||||||
if (fstat64 (fd, &st) < 0)
|
|
||||||
error (EXIT_FAILURE, errno, "cannot stat locale archive template file \"%s\"",
|
|
||||||
archivefname);
|
|
||||||
|
|
||||||
/* Read the header. */
|
|
||||||
if (TEMP_FAILURE_RETRY (read (fd, &head, sizeof (head))) != sizeof (head))
|
|
||||||
error (EXIT_FAILURE, errno, "cannot read archive header");
|
|
||||||
|
|
||||||
ah->fd = fd;
|
|
||||||
ah->mmaped = (head.sumhash_offset
|
|
||||||
+ head.sumhash_size * sizeof (struct sumhashent));
|
|
||||||
if (ah->mmaped > (unsigned long) st.st_size)
|
|
||||||
error (EXIT_FAILURE, 0, "locale archive template file truncated");
|
|
||||||
ah->mmaped = st.st_size;
|
|
||||||
ah->reserved = st.st_size;
|
|
||||||
|
|
||||||
/* Now we know how large the administrative information part is.
|
|
||||||
Map all of it. */
|
|
||||||
ah->addr = mmap64 (NULL, ah->mmaped, PROT_READ, MAP_SHARED, fd, 0);
|
|
||||||
if (ah->addr == MAP_FAILED)
|
|
||||||
error (EXIT_FAILURE, errno, "cannot map archive header");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open the locale archive. */
|
|
||||||
extern void open_archive (struct locarhandle *ah, bool readonly);
|
|
||||||
|
|
||||||
/* Close the locale archive. */
|
|
||||||
extern void close_archive (struct locarhandle *ah);
|
|
||||||
|
|
||||||
/* Add given locale data to the archive. */
|
|
||||||
extern int add_locale_to_archive (struct locarhandle *ah, const char *name,
|
|
||||||
locale_data_t data, bool replace);
|
|
||||||
|
|
||||||
extern void add_alias (struct locarhandle *ah, const char *alias,
|
|
||||||
bool replace, const char *oldname,
|
|
||||||
uint32_t *locrec_offset_p);
|
|
||||||
|
|
||||||
extern struct namehashent *
|
|
||||||
insert_name (struct locarhandle *ah,
|
|
||||||
const char *name, size_t name_len, bool replace);
|
|
||||||
|
|
||||||
struct nameent
|
|
||||||
{
|
|
||||||
char *name;
|
|
||||||
struct locrecent *locrec;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct dataent
|
|
||||||
{
|
|
||||||
const unsigned char *sum;
|
|
||||||
uint32_t file_offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
nameentcmp (const void *a, const void *b)
|
|
||||||
{
|
|
||||||
struct locrecent *la = ((const struct nameent *) a)->locrec;
|
|
||||||
struct locrecent *lb = ((const struct nameent *) b)->locrec;
|
|
||||||
uint32_t start_a = -1, end_a = 0;
|
|
||||||
uint32_t start_b = -1, end_b = 0;
|
|
||||||
int cnt;
|
|
||||||
|
|
||||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
|
||||||
if (cnt != LC_ALL)
|
|
||||||
{
|
|
||||||
if (la->record[cnt].offset < start_a)
|
|
||||||
start_a = la->record[cnt].offset;
|
|
||||||
if (la->record[cnt].offset + la->record[cnt].len > end_a)
|
|
||||||
end_a = la->record[cnt].offset + la->record[cnt].len;
|
|
||||||
}
|
|
||||||
assert (start_a != (uint32_t)-1);
|
|
||||||
assert (end_a != 0);
|
|
||||||
|
|
||||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
|
||||||
if (cnt != LC_ALL)
|
|
||||||
{
|
|
||||||
if (lb->record[cnt].offset < start_b)
|
|
||||||
start_b = lb->record[cnt].offset;
|
|
||||||
if (lb->record[cnt].offset + lb->record[cnt].len > end_b)
|
|
||||||
end_b = lb->record[cnt].offset + lb->record[cnt].len;
|
|
||||||
}
|
|
||||||
assert (start_b != (uint32_t)-1);
|
|
||||||
assert (end_b != 0);
|
|
||||||
|
|
||||||
if (start_a != start_b)
|
|
||||||
return (int)start_a - (int)start_b;
|
|
||||||
return (int)end_a - (int)end_b;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
dataentcmp (const void *a, const void *b)
|
|
||||||
{
|
|
||||||
if (((const struct dataent *) a)->file_offset
|
|
||||||
< ((const struct dataent *) b)->file_offset)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (((const struct dataent *) a)->file_offset
|
|
||||||
> ((const struct dataent *) b)->file_offset)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
sumsearchfn (const void *key, const void *ent)
|
|
||||||
{
|
|
||||||
uint32_t keyn = *(uint32_t *)key;
|
|
||||||
uint32_t entn = ((struct dataent *)ent)->file_offset;
|
|
||||||
|
|
||||||
if (keyn < entn)
|
|
||||||
return -1;
|
|
||||||
if (keyn > entn)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
compute_data (struct locarhandle *ah, struct nameent *name, size_t sumused,
|
|
||||||
struct dataent *files, locale_data_t data)
|
|
||||||
{
|
|
||||||
int cnt;
|
|
||||||
struct locrecent *locrec = name->locrec;
|
|
||||||
struct dataent *file;
|
|
||||||
data[LC_ALL].addr = ((char *) ah->addr) + locrec->record[LC_ALL].offset;
|
|
||||||
data[LC_ALL].size = locrec->record[LC_ALL].len;
|
|
||||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
|
||||||
if (cnt != LC_ALL)
|
|
||||||
{
|
|
||||||
data[cnt].addr = ((char *) ah->addr) + locrec->record[cnt].offset;
|
|
||||||
data[cnt].size = locrec->record[cnt].len;
|
|
||||||
if (data[cnt].addr >= data[LC_ALL].addr
|
|
||||||
&& data[cnt].addr + data[cnt].size
|
|
||||||
<= data[LC_ALL].addr + data[LC_ALL].size)
|
|
||||||
__md5_buffer (data[cnt].addr, data[cnt].size, data[cnt].sum);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
file = bsearch (&locrec->record[cnt].offset, files, sumused,
|
|
||||||
sizeof (*files), sumsearchfn);
|
|
||||||
if (file == NULL)
|
|
||||||
error (EXIT_FAILURE, 0, "inconsistent template file");
|
|
||||||
memcpy (data[cnt].sum, file->sum, sizeof (data[cnt].sum));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
fill_archive (struct locarhandle *tmpl_ah,
|
|
||||||
const char *fname,
|
|
||||||
size_t install_langs_count, char *install_langs_list[],
|
|
||||||
size_t nlist, char *list[],
|
|
||||||
const char *primary)
|
|
||||||
{
|
|
||||||
struct locarhandle ah;
|
|
||||||
struct locarhead *head;
|
|
||||||
int result = 0;
|
|
||||||
struct nameent *names;
|
|
||||||
struct namehashent *namehashtab;
|
|
||||||
size_t cnt, used;
|
|
||||||
struct dataent *files;
|
|
||||||
struct sumhashent *sumhashtab;
|
|
||||||
size_t sumused;
|
|
||||||
struct locrecent *primary_locrec = NULL;
|
|
||||||
struct nameent *primary_nameent = NULL;
|
|
||||||
|
|
||||||
head = tmpl_ah->addr;
|
|
||||||
names = (struct nameent *) malloc (head->namehash_used
|
|
||||||
* sizeof (struct nameent));
|
|
||||||
files = (struct dataent *) malloc (head->sumhash_used
|
|
||||||
* sizeof (struct dataent));
|
|
||||||
if (names == NULL || files == NULL)
|
|
||||||
error (EXIT_FAILURE, errno, "could not allocate tables");
|
|
||||||
|
|
||||||
namehashtab = (struct namehashent *) ((char *) tmpl_ah->addr
|
|
||||||
+ head->namehash_offset);
|
|
||||||
sumhashtab = (struct sumhashent *) ((char *) tmpl_ah->addr
|
|
||||||
+ head->sumhash_offset);
|
|
||||||
|
|
||||||
for (cnt = used = 0; cnt < head->namehash_size; ++cnt)
|
|
||||||
if (namehashtab[cnt].locrec_offset != 0)
|
|
||||||
{
|
|
||||||
char * name;
|
|
||||||
int i;
|
|
||||||
assert (used < head->namehash_used);
|
|
||||||
name = tmpl_ah->addr + namehashtab[cnt].name_offset;
|
|
||||||
if (install_langs_count == 0)
|
|
||||||
{
|
|
||||||
/* Always intstall the entry. */
|
|
||||||
names[used].name = name;
|
|
||||||
names[used++].locrec
|
|
||||||
= (struct locrecent *) ((char *) tmpl_ah->addr +
|
|
||||||
namehashtab[cnt].locrec_offset);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Only install the entry if the user asked for it via
|
|
||||||
--install-langs. */
|
|
||||||
for (i = 0; i < install_langs_count; i++)
|
|
||||||
{
|
|
||||||
/* Add one for "_" and one for the null terminator. */
|
|
||||||
size_t len = strlen (install_langs_list[i]) + 2;
|
|
||||||
char *install_lang = (char *)xmalloc (len);
|
|
||||||
strcpy (install_lang, install_langs_list[i]);
|
|
||||||
if (strchr (install_lang, '_') == NULL)
|
|
||||||
strcat (install_lang, "_");
|
|
||||||
if (strncmp (name, install_lang, strlen (install_lang)) == 0)
|
|
||||||
{
|
|
||||||
names[used].name = name;
|
|
||||||
names[used++].locrec
|
|
||||||
= (struct locrecent *) ((char *)tmpl_ah->addr
|
|
||||||
+ namehashtab[cnt].locrec_offset);
|
|
||||||
}
|
|
||||||
free (install_lang);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sort the names. */
|
|
||||||
qsort (names, used, sizeof (struct nameent), nameentcmp);
|
|
||||||
|
|
||||||
for (cnt = sumused = 0; cnt < head->sumhash_size; ++cnt)
|
|
||||||
if (sumhashtab[cnt].file_offset != 0)
|
|
||||||
{
|
|
||||||
assert (sumused < head->sumhash_used);
|
|
||||||
files[sumused].sum = (const unsigned char *) sumhashtab[cnt].sum;
|
|
||||||
files[sumused++].file_offset = sumhashtab[cnt].file_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sort by file locations. */
|
|
||||||
qsort (files, sumused, sizeof (struct dataent), dataentcmp);
|
|
||||||
|
|
||||||
/* Open the archive. This call never returns if we cannot
|
|
||||||
successfully open the archive. */
|
|
||||||
ah.fname = NULL;
|
|
||||||
if (fname != NULL)
|
|
||||||
ah.fname = fname;
|
|
||||||
open_archive (&ah, false);
|
|
||||||
|
|
||||||
if (primary != NULL)
|
|
||||||
{
|
|
||||||
for (cnt = 0; cnt < used; ++cnt)
|
|
||||||
if (strcmp (names[cnt].name, primary) == 0)
|
|
||||||
break;
|
|
||||||
if (cnt < used)
|
|
||||||
{
|
|
||||||
locale_data_t data;
|
|
||||||
|
|
||||||
compute_data (tmpl_ah, &names[cnt], sumused, files, data);
|
|
||||||
result |= add_locale_to_archive (&ah, primary, data, 0);
|
|
||||||
primary_locrec = names[cnt].locrec;
|
|
||||||
primary_nameent = &names[cnt];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (cnt = 0; cnt < used; ++cnt)
|
|
||||||
if (&names[cnt] == primary_nameent)
|
|
||||||
continue;
|
|
||||||
else if ((cnt > 0 && names[cnt - 1].locrec == names[cnt].locrec)
|
|
||||||
|| names[cnt].locrec == primary_locrec)
|
|
||||||
{
|
|
||||||
const char *oldname;
|
|
||||||
struct namehashent *namehashent;
|
|
||||||
uint32_t locrec_offset;
|
|
||||||
|
|
||||||
if (names[cnt].locrec == primary_locrec)
|
|
||||||
oldname = primary;
|
|
||||||
else
|
|
||||||
oldname = names[cnt - 1].name;
|
|
||||||
namehashent = insert_name (&ah, oldname, strlen (oldname), true);
|
|
||||||
assert (namehashent->name_offset != 0);
|
|
||||||
assert (namehashent->locrec_offset != 0);
|
|
||||||
locrec_offset = namehashent->locrec_offset;
|
|
||||||
add_alias (&ah, names[cnt].name, 0, oldname, &locrec_offset);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
locale_data_t data;
|
|
||||||
|
|
||||||
compute_data (tmpl_ah, &names[cnt], sumused, files, data);
|
|
||||||
result |= add_locale_to_archive (&ah, names[cnt].name, data, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (nlist-- > 0)
|
|
||||||
{
|
|
||||||
const char *fname = *list++;
|
|
||||||
size_t fnamelen = strlen (fname);
|
|
||||||
struct stat64 st;
|
|
||||||
DIR *dirp;
|
|
||||||
struct dirent64 *d;
|
|
||||||
int seen;
|
|
||||||
locale_data_t data;
|
|
||||||
int cnt;
|
|
||||||
|
|
||||||
/* First see whether this really is a directory and whether it
|
|
||||||
contains all the require locale category files. */
|
|
||||||
if (stat64 (fname, &st) < 0)
|
|
||||||
{
|
|
||||||
error (0, 0, "stat of \"%s\" failed: %s: ignored", fname,
|
|
||||||
strerror (errno));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!S_ISDIR (st.st_mode))
|
|
||||||
{
|
|
||||||
error (0, 0, "\"%s\" is no directory; ignored", fname);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
dirp = opendir (fname);
|
|
||||||
if (dirp == NULL)
|
|
||||||
{
|
|
||||||
error (0, 0, "cannot open directory \"%s\": %s: ignored",
|
|
||||||
fname, strerror (errno));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
seen = 0;
|
|
||||||
while ((d = readdir64 (dirp)) != NULL)
|
|
||||||
{
|
|
||||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
|
||||||
if (cnt != LC_ALL)
|
|
||||||
if (strcmp (d->d_name, locnames[cnt]) == 0)
|
|
||||||
{
|
|
||||||
unsigned char d_type;
|
|
||||||
|
|
||||||
/* We have an object of the required name. If it's
|
|
||||||
a directory we have to look at a file with the
|
|
||||||
prefix "SYS_". Otherwise we have found what we
|
|
||||||
are looking for. */
|
|
||||||
#ifdef _DIRENT_HAVE_D_TYPE
|
|
||||||
d_type = d->d_type;
|
|
||||||
|
|
||||||
if (d_type != DT_REG)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
char fullname[fnamelen + 2 * strlen (d->d_name) + 7];
|
|
||||||
|
|
||||||
#ifdef _DIRENT_HAVE_D_TYPE
|
|
||||||
if (d_type == DT_UNKNOWN)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
strcpy (stpcpy (stpcpy (fullname, fname), "/"),
|
|
||||||
d->d_name);
|
|
||||||
|
|
||||||
if (stat64 (fullname, &st) == -1)
|
|
||||||
/* We cannot stat the file, ignore it. */
|
|
||||||
break;
|
|
||||||
|
|
||||||
d_type = IFTODT (st.st_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d_type == DT_DIR)
|
|
||||||
{
|
|
||||||
/* We have to do more tests. The file is a
|
|
||||||
directory and it therefore must contain a
|
|
||||||
regular file with the same name except a
|
|
||||||
"SYS_" prefix. */
|
|
||||||
char *t = stpcpy (stpcpy (fullname, fname), "/");
|
|
||||||
strcpy (stpcpy (stpcpy (t, d->d_name), "/SYS_"),
|
|
||||||
d->d_name);
|
|
||||||
|
|
||||||
if (stat64 (fullname, &st) == -1)
|
|
||||||
/* There is no SYS_* file or we cannot
|
|
||||||
access it. */
|
|
||||||
break;
|
|
||||||
|
|
||||||
d_type = IFTODT (st.st_mode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we found a regular file (eventually after
|
|
||||||
following a symlink) we are successful. */
|
|
||||||
if (d_type == DT_REG)
|
|
||||||
++seen;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir (dirp);
|
|
||||||
|
|
||||||
if (seen != __LC_LAST - 1)
|
|
||||||
{
|
|
||||||
/* We don't have all locale category files. Ignore the name. */
|
|
||||||
error (0, 0, "incomplete set of locale files in \"%s\"",
|
|
||||||
fname);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add the files to the archive. To do this we first compute
|
|
||||||
sizes and the MD5 sums of all the files. */
|
|
||||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
|
||||||
if (cnt != LC_ALL)
|
|
||||||
{
|
|
||||||
char fullname[fnamelen + 2 * strlen (locnames[cnt]) + 7];
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
strcpy (stpcpy (stpcpy (fullname, fname), "/"), locnames[cnt]);
|
|
||||||
fd = open64 (fullname, O_RDONLY);
|
|
||||||
if (fd == -1 || fstat64 (fd, &st) == -1)
|
|
||||||
{
|
|
||||||
/* Cannot read the file. */
|
|
||||||
if (fd != -1)
|
|
||||||
close (fd);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (S_ISDIR (st.st_mode))
|
|
||||||
{
|
|
||||||
char *t;
|
|
||||||
close (fd);
|
|
||||||
t = stpcpy (stpcpy (fullname, fname), "/");
|
|
||||||
strcpy (stpcpy (stpcpy (t, locnames[cnt]), "/SYS_"),
|
|
||||||
locnames[cnt]);
|
|
||||||
|
|
||||||
fd = open64 (fullname, O_RDONLY);
|
|
||||||
if (fd == -1 || fstat64 (fd, &st) == -1
|
|
||||||
|| !S_ISREG (st.st_mode))
|
|
||||||
{
|
|
||||||
if (fd != -1)
|
|
||||||
close (fd);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Map the file. */
|
|
||||||
data[cnt].addr = mmap64 (NULL, st.st_size, PROT_READ, MAP_SHARED,
|
|
||||||
fd, 0);
|
|
||||||
if (data[cnt].addr == MAP_FAILED)
|
|
||||||
{
|
|
||||||
/* Cannot map it. */
|
|
||||||
close (fd);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
data[cnt].size = st.st_size;
|
|
||||||
__md5_buffer (data[cnt].addr, st.st_size, data[cnt].sum);
|
|
||||||
|
|
||||||
/* We don't need the file descriptor anymore. */
|
|
||||||
close (fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cnt != __LC_LAST)
|
|
||||||
{
|
|
||||||
while (cnt-- > 0)
|
|
||||||
if (cnt != LC_ALL)
|
|
||||||
munmap (data[cnt].addr, data[cnt].size);
|
|
||||||
|
|
||||||
error (0, 0, "cannot read all files in \"%s\": ignored", fname);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
result |= add_locale_to_archive (&ah, basename (fname), data, 0);
|
|
||||||
|
|
||||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
|
||||||
if (cnt != LC_ALL)
|
|
||||||
munmap (data[cnt].addr, data[cnt].size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We are done. */
|
|
||||||
close_archive (&ah);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void usage()
|
|
||||||
{
|
|
||||||
printf ("\
|
|
||||||
Usage: build-locale-archive [OPTION]... [TEMPLATE-FILE] [ARCHIVE-FILE]\n\
|
|
||||||
Builds a locale archive from a template file.\n\
|
|
||||||
Options:\n\
|
|
||||||
-h, --help Print this usage message.\n\
|
|
||||||
-v, --verbose Verbose execution.\n\
|
|
||||||
-l, --install-langs=LIST Only include locales given in LIST into the \n\
|
|
||||||
locale archive. LIST is a colon separated list\n\
|
|
||||||
of locale prefixes, for example \"de:en:ja\".\n\
|
|
||||||
The special argument \"all\" means to install\n\
|
|
||||||
all languages and it must be present by itself.\n\
|
|
||||||
If \"all\" is present with any other language it\n\
|
|
||||||
will be treated as the name of a locale.\n\
|
|
||||||
If the --install-langs option is missing, all\n\
|
|
||||||
locales are installed. The colon separated list\n\
|
|
||||||
can contain any strings matching the beginning of\n\
|
|
||||||
locale names.\n\
|
|
||||||
If a string does not contain a \"_\", it is added.\n\
|
|
||||||
Examples:\n\
|
|
||||||
--install-langs=\"en\"\n\
|
|
||||||
installs en_US, en_US.iso88591,\n\
|
|
||||||
en_US.iso885915, en_US.utf8,\n\
|
|
||||||
en_GB ...\n\
|
|
||||||
--install-langs=\"en_US.utf8\"\n\
|
|
||||||
installs only en_US.utf8.\n\
|
|
||||||
--install-langs=\"ko\"\n\
|
|
||||||
installs ko_KR, ko_KR.euckr,\n\
|
|
||||||
ko_KR.utf8 but *not* kok_IN\n\
|
|
||||||
because \"ko\" does not contain\n\
|
|
||||||
\"_\" and it is silently added\n\
|
|
||||||
--install-langs\"ko:kok\"\n\
|
|
||||||
installs ko_KR, ko_KR.euckr,\n\
|
|
||||||
ko_KR.utf8, kok_IN, and\n\
|
|
||||||
kok_IN.utf8.\n\
|
|
||||||
--install-langs=\"POSIX\" will\n\
|
|
||||||
installs *no* locales at all\n\
|
|
||||||
because POSIX matches none of\n\
|
|
||||||
the locales. Actually, any string\n\
|
|
||||||
matching nothing will do that.\n\
|
|
||||||
POSIX and C will always be\n\
|
|
||||||
available because they are\n\
|
|
||||||
builtin.\n\
|
|
||||||
Aliases are installed as well,\n\
|
|
||||||
i.e. --install-langs=\"de\"\n\
|
|
||||||
will install not only every locale starting with\n\
|
|
||||||
\"de\" but also the aliases \"deutsch\"\n\
|
|
||||||
and and \"german\" although the latter does not\n\
|
|
||||||
start with \"de\".\n\
|
|
||||||
\n\
|
|
||||||
If the arguments TEMPLATE-FILE and ARCHIVE-FILE are not given the locations\n\
|
|
||||||
where the glibc used expects these files are used by default.\n\
|
|
||||||
");
|
|
||||||
}
|
|
||||||
|
|
||||||
int main (int argc, char *argv[])
|
|
||||||
{
|
|
||||||
char path[4096];
|
|
||||||
DIR *dirp;
|
|
||||||
struct dirent64 *d;
|
|
||||||
struct stat64 st;
|
|
||||||
char *list[16384], *primary;
|
|
||||||
char *lang;
|
|
||||||
int install_langs_count = 0;
|
|
||||||
int i;
|
|
||||||
char *install_langs_arg, *ila_start;
|
|
||||||
char **install_langs_list = NULL;
|
|
||||||
unsigned int cnt = 0;
|
|
||||||
struct locarhandle tmpl_ah;
|
|
||||||
char *new_locar_fname = NULL;
|
|
||||||
size_t loc_path_len = strlen (loc_path);
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
int c;
|
|
||||||
|
|
||||||
static struct option long_options[] =
|
|
||||||
{
|
|
||||||
{"help", no_argument, 0, 'h'},
|
|
||||||
{"verbose", no_argument, 0, 'v'},
|
|
||||||
{"install-langs", required_argument, 0, 'l'},
|
|
||||||
{0, 0, 0, 0}
|
|
||||||
};
|
|
||||||
/* getopt_long stores the option index here. */
|
|
||||||
int option_index = 0;
|
|
||||||
|
|
||||||
c = getopt_long (argc, argv, "vhl:",
|
|
||||||
long_options, &option_index);
|
|
||||||
|
|
||||||
/* Detect the end of the options. */
|
|
||||||
if (c == -1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
printf ("unknown option %s", long_options[option_index].name);
|
|
||||||
if (optarg)
|
|
||||||
printf (" with arg %s", optarg);
|
|
||||||
printf ("\n");
|
|
||||||
usage ();
|
|
||||||
exit (1);
|
|
||||||
|
|
||||||
case 'v':
|
|
||||||
verbose = 1;
|
|
||||||
be_quiet = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'h':
|
|
||||||
usage ();
|
|
||||||
exit (0);
|
|
||||||
|
|
||||||
case 'l':
|
|
||||||
install_langs_arg = ila_start = strdup (optarg);
|
|
||||||
/* If the argument to --install-lang is "all", do
|
|
||||||
not limit the list of languages to install and install
|
|
||||||
them all. We do not support installing a single locale
|
|
||||||
called "all". */
|
|
||||||
#define MAGIC_INSTALL_ALL "all"
|
|
||||||
if (install_langs_arg != NULL
|
|
||||||
&& install_langs_arg[0] != '\0'
|
|
||||||
&& !(strncmp(install_langs_arg, MAGIC_INSTALL_ALL,
|
|
||||||
strlen(MAGIC_INSTALL_ALL)) == 0
|
|
||||||
&& strlen (install_langs_arg) == 3))
|
|
||||||
{
|
|
||||||
/* Count the number of languages we will install. */
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
lang = strtok(install_langs_arg, ":;,");
|
|
||||||
if (lang == NULL)
|
|
||||||
break;
|
|
||||||
install_langs_count++;
|
|
||||||
install_langs_arg = NULL;
|
|
||||||
}
|
|
||||||
free (ila_start);
|
|
||||||
|
|
||||||
/* Reject an entire string made up of delimiters. */
|
|
||||||
if (install_langs_count == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Copy the list. */
|
|
||||||
install_langs_list = (char **)xmalloc (sizeof(char *) * install_langs_count);
|
|
||||||
install_langs_arg = ila_start = strdup (optarg);
|
|
||||||
install_langs_count = 0;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
lang = strtok(install_langs_arg, ":;,");
|
|
||||||
if (lang == NULL)
|
|
||||||
break;
|
|
||||||
install_langs_list[install_langs_count] = lang;
|
|
||||||
install_langs_count++;
|
|
||||||
install_langs_arg = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '?':
|
|
||||||
/* getopt_long already printed an error message. */
|
|
||||||
usage ();
|
|
||||||
exit (0);
|
|
||||||
|
|
||||||
default:
|
|
||||||
abort ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tmpl_ah.fname = NULL;
|
|
||||||
if (optind < argc)
|
|
||||||
tmpl_ah.fname = argv[optind];
|
|
||||||
if (optind + 1 < argc)
|
|
||||||
new_locar_fname = argv[optind + 1];
|
|
||||||
if (verbose)
|
|
||||||
{
|
|
||||||
if (tmpl_ah.fname)
|
|
||||||
printf("input archive file specified on command line: %s\n",
|
|
||||||
tmpl_ah.fname);
|
|
||||||
else
|
|
||||||
printf("using default input archive file.\n");
|
|
||||||
if (new_locar_fname)
|
|
||||||
printf("output archive file specified on command line: %s\n",
|
|
||||||
new_locar_fname);
|
|
||||||
else
|
|
||||||
printf("using default output archive file.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
dirp = opendir (loc_path);
|
|
||||||
if (dirp == NULL)
|
|
||||||
error (EXIT_FAILURE, errno, "cannot open directory \"%s\"", loc_path);
|
|
||||||
|
|
||||||
open_tmpl_archive (&tmpl_ah);
|
|
||||||
|
|
||||||
if (new_locar_fname)
|
|
||||||
unlink (new_locar_fname);
|
|
||||||
else
|
|
||||||
unlink (locar_file);
|
|
||||||
primary = getenv ("LC_ALL");
|
|
||||||
if (primary == NULL)
|
|
||||||
primary = getenv ("LANG");
|
|
||||||
if (primary != NULL)
|
|
||||||
{
|
|
||||||
if (strncmp (primary, "ja", 2) != 0
|
|
||||||
&& strncmp (primary, "ko", 2) != 0
|
|
||||||
&& strncmp (primary, "zh", 2) != 0)
|
|
||||||
{
|
|
||||||
char *ptr = malloc (strlen (primary) + strlen (".utf8") + 1), *p, *q;
|
|
||||||
/* This leads to invalid locales sometimes:
|
|
||||||
de_DE.iso885915@euro -> de_DE.utf8@euro */
|
|
||||||
if (ptr != NULL)
|
|
||||||
{
|
|
||||||
p = ptr;
|
|
||||||
q = primary;
|
|
||||||
while (*q && *q != '.' && *q != '@')
|
|
||||||
*p++ = *q++;
|
|
||||||
if (*q == '.')
|
|
||||||
while (*q && *q != '@')
|
|
||||||
q++;
|
|
||||||
p = stpcpy (p, ".utf8");
|
|
||||||
strcpy (p, q);
|
|
||||||
primary = ptr;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
primary = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy (path, loc_path, loc_path_len);
|
|
||||||
|
|
||||||
while ((d = readdir64 (dirp)) != NULL)
|
|
||||||
{
|
|
||||||
if (strcmp (d->d_name, ".") == 0 || strcmp (d->d_name, "..") == 0)
|
|
||||||
continue;
|
|
||||||
if (strchr (d->d_name, '_') == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
size_t d_name_len = strlen (d->d_name);
|
|
||||||
if (loc_path_len + d_name_len + 1 > sizeof (path))
|
|
||||||
{
|
|
||||||
error (0, 0, "too long filename \"%s\"", d->d_name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy (path + loc_path_len, d->d_name, d_name_len + 1);
|
|
||||||
if (stat64 (path, &st) < 0)
|
|
||||||
{
|
|
||||||
error (0, errno, "cannot stat \"%s\"", path);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (! S_ISDIR (st.st_mode))
|
|
||||||
continue;
|
|
||||||
if (cnt == 16384)
|
|
||||||
{
|
|
||||||
error (0, 0, "too many directories in \"%s\"", loc_path);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
list[cnt] = strdup (path);
|
|
||||||
if (list[cnt] == NULL)
|
|
||||||
{
|
|
||||||
error (0, errno, "cannot add file to list \"%s\"", path);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (primary != NULL && cnt > 0 && strcmp (primary, d->d_name) == 0)
|
|
||||||
{
|
|
||||||
char *p = list[0];
|
|
||||||
list[0] = list[cnt];
|
|
||||||
list[cnt] = p;
|
|
||||||
}
|
|
||||||
cnt++;
|
|
||||||
}
|
|
||||||
closedir (dirp);
|
|
||||||
/* Store the archive to the file specified as the second argument on the
|
|
||||||
command line or the default locale archive. */
|
|
||||||
fill_archive (&tmpl_ah, new_locar_fname,
|
|
||||||
install_langs_count, install_langs_list,
|
|
||||||
cnt, list, primary);
|
|
||||||
close_archive (&tmpl_ah);
|
|
||||||
truncate (tmpl_file, 0);
|
|
||||||
if (install_langs_count > 0)
|
|
||||||
{
|
|
||||||
free (ila_start);
|
|
||||||
free (install_langs_list);
|
|
||||||
}
|
|
||||||
char *tz_argv[] = { "/usr/sbin/tzdata-update", NULL };
|
|
||||||
execve (tz_argv[0], (char *const *)tz_argv, (char *const *)&tz_argv[1]);
|
|
||||||
exit (0);
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Wed Jul 4 16:16:57 2018 +0200
|
|
||||||
|
|
||||||
Makeconfig (ASFLAGS): Always append required assembler flags.
|
|
||||||
|
|
||||||
Submitted upstream here:
|
|
||||||
|
|
||||||
https://sourceware.org/ml/libc-alpha/2018-07/msg00077.html
|
|
||||||
|
|
||||||
Otherwise, we lose essential flags such as -Wa,--noexecstack due to
|
|
||||||
the way += works in make due to the ASFLAGS command line override.
|
|
||||||
|
|
||||||
diff --git a/Makeconfig b/Makeconfig
|
|
||||||
index b0b27f0113ac18b8..92e76d6200bbcd5b 100644
|
|
||||||
--- a/Makeconfig
|
|
||||||
+++ b/Makeconfig
|
|
||||||
@@ -1047,7 +1047,7 @@ endif
|
|
||||||
ifndef ASFLAGS
|
|
||||||
ASFLAGS := $(filter -g% -fdebug-prefix-map=%,$(CFLAGS))
|
|
||||||
endif
|
|
||||||
-ASFLAGS += -Werror=undef $(ASFLAGS-config) $(asflags-cpu)
|
|
||||||
+override ASFLAGS += -Werror=undef $(ASFLAGS-config) $(asflags-cpu)
|
|
||||||
|
|
||||||
ifndef BUILD_CC
|
|
||||||
BUILD_CC = $(CC)
|
|
980
SOURCES/glibc-c-utf8-locale-1.patch
Normal file
980
SOURCES/glibc-c-utf8-locale-1.patch
Normal file
@ -0,0 +1,980 @@
|
|||||||
|
commit f5117c6504888fab5423282a4607c552b90fd3f9
|
||||||
|
Author: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
Date: Thu Jul 29 22:45:39 2021 -0400
|
||||||
|
|
||||||
|
Add 'codepoint_collation' support for LC_COLLATE.
|
||||||
|
|
||||||
|
Support a new directive 'codepoint_collation' in the LC_COLLATE
|
||||||
|
section of a locale source file. This new directive causes all
|
||||||
|
collation rules to be dropped and instead STRCMP (strcmp or
|
||||||
|
wcscmp) is used for collation of the input character set. This
|
||||||
|
is required to allow for a C.UTF-8 that contains zero collation
|
||||||
|
rules (minimal size) and sorts using code point sorting.
|
||||||
|
|
||||||
|
To date the only implementation of a locale with zero collation
|
||||||
|
rules is the C/POSIX locale. The C/POSIX locale provides
|
||||||
|
identity tables for _NL_COLLATE_COLLSEQMB and
|
||||||
|
_NL_COLLATE_COLLSEQWC that map to ASCII even though it has zero
|
||||||
|
rules. This has lead to existing fnmatch, regexec, and regcomp
|
||||||
|
implementations that require these tables. It is not correct
|
||||||
|
to use these tables when nrules == 0, but the conservative fix
|
||||||
|
is to provide these tables when nrules == 0. This assures that
|
||||||
|
existing static applications using a new C.UTF-8 locale with
|
||||||
|
'codepoint_collation' at least have functional range expressions
|
||||||
|
with ASCII e.g. [0-9] or [a-z]. Such static applications would
|
||||||
|
not have the fixes to fnmatch, regexec and regcomp that avoid
|
||||||
|
the use of the tables when nrules == 0. Future fixes to fnmatch,
|
||||||
|
regexec, and regcomp would allow range expressions to use the
|
||||||
|
full set of code points for such ranges.
|
||||||
|
|
||||||
|
Tested on x86_64 and i686 without regression.
|
||||||
|
|
||||||
|
Reviewed-by: Florian Weimer <fweimer@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/locale/C-collate-seq.c b/locale/C-collate-seq.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..4fb82cb8357936b6
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/locale/C-collate-seq.c
|
||||||
|
@@ -0,0 +1,100 @@
|
||||||
|
+/* Copyright (C) 1995-2021 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <https://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <stdint.h>
|
||||||
|
+
|
||||||
|
+static const char collseqmb[] =
|
||||||
|
+{
|
||||||
|
+ '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
|
||||||
|
+ '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
|
||||||
|
+ '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
|
||||||
|
+ '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f',
|
||||||
|
+ '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27',
|
||||||
|
+ '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f',
|
||||||
|
+ '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37',
|
||||||
|
+ '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f',
|
||||||
|
+ '\x40', '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47',
|
||||||
|
+ '\x48', '\x49', '\x4a', '\x4b', '\x4c', '\x4d', '\x4e', '\x4f',
|
||||||
|
+ '\x50', '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57',
|
||||||
|
+ '\x58', '\x59', '\x5a', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f',
|
||||||
|
+ '\x60', '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67',
|
||||||
|
+ '\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f',
|
||||||
|
+ '\x70', '\x71', '\x72', '\x73', '\x74', '\x75', '\x76', '\x77',
|
||||||
|
+ '\x78', '\x79', '\x7a', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f',
|
||||||
|
+ '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87',
|
||||||
|
+ '\x88', '\x89', '\x8a', '\x8b', '\x8c', '\x8d', '\x8e', '\x8f',
|
||||||
|
+ '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97',
|
||||||
|
+ '\x98', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f',
|
||||||
|
+ '\xa0', '\xa1', '\xa2', '\xa3', '\xa4', '\xa5', '\xa6', '\xa7',
|
||||||
|
+ '\xa8', '\xa9', '\xaa', '\xab', '\xac', '\xad', '\xae', '\xaf',
|
||||||
|
+ '\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7',
|
||||||
|
+ '\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf',
|
||||||
|
+ '\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7',
|
||||||
|
+ '\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf',
|
||||||
|
+ '\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7',
|
||||||
|
+ '\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf',
|
||||||
|
+ '\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7',
|
||||||
|
+ '\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef',
|
||||||
|
+ '\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7',
|
||||||
|
+ '\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff'
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* This table must be 256 bytes in size. We index bytes into the
|
||||||
|
+ table to find the collation sequence. */
|
||||||
|
+_Static_assert (sizeof (collseqmb) == 256);
|
||||||
|
+
|
||||||
|
+static const uint32_t collseqwc[] =
|
||||||
|
+{
|
||||||
|
+ 8, 1, 8, 0x0, 0xff,
|
||||||
|
+ /* 1st-level table */
|
||||||
|
+ 6 * sizeof (uint32_t),
|
||||||
|
+ /* 2nd-level table */
|
||||||
|
+ 7 * sizeof (uint32_t),
|
||||||
|
+ /* 3rd-level table */
|
||||||
|
+ L'\x00', L'\x01', L'\x02', L'\x03', L'\x04', L'\x05', L'\x06', L'\x07',
|
||||||
|
+ L'\x08', L'\x09', L'\x0a', L'\x0b', L'\x0c', L'\x0d', L'\x0e', L'\x0f',
|
||||||
|
+ L'\x10', L'\x11', L'\x12', L'\x13', L'\x14', L'\x15', L'\x16', L'\x17',
|
||||||
|
+ L'\x18', L'\x19', L'\x1a', L'\x1b', L'\x1c', L'\x1d', L'\x1e', L'\x1f',
|
||||||
|
+ L'\x20', L'\x21', L'\x22', L'\x23', L'\x24', L'\x25', L'\x26', L'\x27',
|
||||||
|
+ L'\x28', L'\x29', L'\x2a', L'\x2b', L'\x2c', L'\x2d', L'\x2e', L'\x2f',
|
||||||
|
+ L'\x30', L'\x31', L'\x32', L'\x33', L'\x34', L'\x35', L'\x36', L'\x37',
|
||||||
|
+ L'\x38', L'\x39', L'\x3a', L'\x3b', L'\x3c', L'\x3d', L'\x3e', L'\x3f',
|
||||||
|
+ L'\x40', L'\x41', L'\x42', L'\x43', L'\x44', L'\x45', L'\x46', L'\x47',
|
||||||
|
+ L'\x48', L'\x49', L'\x4a', L'\x4b', L'\x4c', L'\x4d', L'\x4e', L'\x4f',
|
||||||
|
+ L'\x50', L'\x51', L'\x52', L'\x53', L'\x54', L'\x55', L'\x56', L'\x57',
|
||||||
|
+ L'\x58', L'\x59', L'\x5a', L'\x5b', L'\x5c', L'\x5d', L'\x5e', L'\x5f',
|
||||||
|
+ L'\x60', L'\x61', L'\x62', L'\x63', L'\x64', L'\x65', L'\x66', L'\x67',
|
||||||
|
+ L'\x68', L'\x69', L'\x6a', L'\x6b', L'\x6c', L'\x6d', L'\x6e', L'\x6f',
|
||||||
|
+ L'\x70', L'\x71', L'\x72', L'\x73', L'\x74', L'\x75', L'\x76', L'\x77',
|
||||||
|
+ L'\x78', L'\x79', L'\x7a', L'\x7b', L'\x7c', L'\x7d', L'\x7e', L'\x7f',
|
||||||
|
+ L'\x80', L'\x81', L'\x82', L'\x83', L'\x84', L'\x85', L'\x86', L'\x87',
|
||||||
|
+ L'\x88', L'\x89', L'\x8a', L'\x8b', L'\x8c', L'\x8d', L'\x8e', L'\x8f',
|
||||||
|
+ L'\x90', L'\x91', L'\x92', L'\x93', L'\x94', L'\x95', L'\x96', L'\x97',
|
||||||
|
+ L'\x98', L'\x99', L'\x9a', L'\x9b', L'\x9c', L'\x9d', L'\x9e', L'\x9f',
|
||||||
|
+ L'\xa0', L'\xa1', L'\xa2', L'\xa3', L'\xa4', L'\xa5', L'\xa6', L'\xa7',
|
||||||
|
+ L'\xa8', L'\xa9', L'\xaa', L'\xab', L'\xac', L'\xad', L'\xae', L'\xaf',
|
||||||
|
+ L'\xb0', L'\xb1', L'\xb2', L'\xb3', L'\xb4', L'\xb5', L'\xb6', L'\xb7',
|
||||||
|
+ L'\xb8', L'\xb9', L'\xba', L'\xbb', L'\xbc', L'\xbd', L'\xbe', L'\xbf',
|
||||||
|
+ L'\xc0', L'\xc1', L'\xc2', L'\xc3', L'\xc4', L'\xc5', L'\xc6', L'\xc7',
|
||||||
|
+ L'\xc8', L'\xc9', L'\xca', L'\xcb', L'\xcc', L'\xcd', L'\xce', L'\xcf',
|
||||||
|
+ L'\xd0', L'\xd1', L'\xd2', L'\xd3', L'\xd4', L'\xd5', L'\xd6', L'\xd7',
|
||||||
|
+ L'\xd8', L'\xd9', L'\xda', L'\xdb', L'\xdc', L'\xdd', L'\xde', L'\xdf',
|
||||||
|
+ L'\xe0', L'\xe1', L'\xe2', L'\xe3', L'\xe4', L'\xe5', L'\xe6', L'\xe7',
|
||||||
|
+ L'\xe8', L'\xe9', L'\xea', L'\xeb', L'\xec', L'\xed', L'\xee', L'\xef',
|
||||||
|
+ L'\xf0', L'\xf1', L'\xf2', L'\xf3', L'\xf4', L'\xf5', L'\xf6', L'\xf7',
|
||||||
|
+ L'\xf8', L'\xf9', L'\xfa', L'\xfb', L'\xfc', L'\xfd', L'\xfe', L'\xff'
|
||||||
|
+};
|
||||||
|
diff --git a/locale/C-collate.c b/locale/C-collate.c
|
||||||
|
index 76d9373683314943..120ce0a40aeb9a0f 100644
|
||||||
|
--- a/locale/C-collate.c
|
||||||
|
+++ b/locale/C-collate.c
|
||||||
|
@@ -20,83 +20,7 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "localeinfo.h"
|
||||||
|
|
||||||
|
-static const char collseqmb[] =
|
||||||
|
-{
|
||||||
|
- '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
|
||||||
|
- '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
|
||||||
|
- '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
|
||||||
|
- '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f',
|
||||||
|
- '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27',
|
||||||
|
- '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f',
|
||||||
|
- '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37',
|
||||||
|
- '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f',
|
||||||
|
- '\x40', '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47',
|
||||||
|
- '\x48', '\x49', '\x4a', '\x4b', '\x4c', '\x4d', '\x4e', '\x4f',
|
||||||
|
- '\x50', '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57',
|
||||||
|
- '\x58', '\x59', '\x5a', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f',
|
||||||
|
- '\x60', '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67',
|
||||||
|
- '\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f',
|
||||||
|
- '\x70', '\x71', '\x72', '\x73', '\x74', '\x75', '\x76', '\x77',
|
||||||
|
- '\x78', '\x79', '\x7a', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f',
|
||||||
|
- '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87',
|
||||||
|
- '\x88', '\x89', '\x8a', '\x8b', '\x8c', '\x8d', '\x8e', '\x8f',
|
||||||
|
- '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97',
|
||||||
|
- '\x98', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f',
|
||||||
|
- '\xa0', '\xa1', '\xa2', '\xa3', '\xa4', '\xa5', '\xa6', '\xa7',
|
||||||
|
- '\xa8', '\xa9', '\xaa', '\xab', '\xac', '\xad', '\xae', '\xaf',
|
||||||
|
- '\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7',
|
||||||
|
- '\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf',
|
||||||
|
- '\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7',
|
||||||
|
- '\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf',
|
||||||
|
- '\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7',
|
||||||
|
- '\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf',
|
||||||
|
- '\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7',
|
||||||
|
- '\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef',
|
||||||
|
- '\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7',
|
||||||
|
- '\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff'
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-static const uint32_t collseqwc[] =
|
||||||
|
-{
|
||||||
|
- 8, 1, 8, 0x0, 0xff,
|
||||||
|
- /* 1st-level table */
|
||||||
|
- 6 * sizeof (uint32_t),
|
||||||
|
- /* 2nd-level table */
|
||||||
|
- 7 * sizeof (uint32_t),
|
||||||
|
- /* 3rd-level table */
|
||||||
|
- L'\x00', L'\x01', L'\x02', L'\x03', L'\x04', L'\x05', L'\x06', L'\x07',
|
||||||
|
- L'\x08', L'\x09', L'\x0a', L'\x0b', L'\x0c', L'\x0d', L'\x0e', L'\x0f',
|
||||||
|
- L'\x10', L'\x11', L'\x12', L'\x13', L'\x14', L'\x15', L'\x16', L'\x17',
|
||||||
|
- L'\x18', L'\x19', L'\x1a', L'\x1b', L'\x1c', L'\x1d', L'\x1e', L'\x1f',
|
||||||
|
- L'\x20', L'\x21', L'\x22', L'\x23', L'\x24', L'\x25', L'\x26', L'\x27',
|
||||||
|
- L'\x28', L'\x29', L'\x2a', L'\x2b', L'\x2c', L'\x2d', L'\x2e', L'\x2f',
|
||||||
|
- L'\x30', L'\x31', L'\x32', L'\x33', L'\x34', L'\x35', L'\x36', L'\x37',
|
||||||
|
- L'\x38', L'\x39', L'\x3a', L'\x3b', L'\x3c', L'\x3d', L'\x3e', L'\x3f',
|
||||||
|
- L'\x40', L'\x41', L'\x42', L'\x43', L'\x44', L'\x45', L'\x46', L'\x47',
|
||||||
|
- L'\x48', L'\x49', L'\x4a', L'\x4b', L'\x4c', L'\x4d', L'\x4e', L'\x4f',
|
||||||
|
- L'\x50', L'\x51', L'\x52', L'\x53', L'\x54', L'\x55', L'\x56', L'\x57',
|
||||||
|
- L'\x58', L'\x59', L'\x5a', L'\x5b', L'\x5c', L'\x5d', L'\x5e', L'\x5f',
|
||||||
|
- L'\x60', L'\x61', L'\x62', L'\x63', L'\x64', L'\x65', L'\x66', L'\x67',
|
||||||
|
- L'\x68', L'\x69', L'\x6a', L'\x6b', L'\x6c', L'\x6d', L'\x6e', L'\x6f',
|
||||||
|
- L'\x70', L'\x71', L'\x72', L'\x73', L'\x74', L'\x75', L'\x76', L'\x77',
|
||||||
|
- L'\x78', L'\x79', L'\x7a', L'\x7b', L'\x7c', L'\x7d', L'\x7e', L'\x7f',
|
||||||
|
- L'\x80', L'\x81', L'\x82', L'\x83', L'\x84', L'\x85', L'\x86', L'\x87',
|
||||||
|
- L'\x88', L'\x89', L'\x8a', L'\x8b', L'\x8c', L'\x8d', L'\x8e', L'\x8f',
|
||||||
|
- L'\x90', L'\x91', L'\x92', L'\x93', L'\x94', L'\x95', L'\x96', L'\x97',
|
||||||
|
- L'\x98', L'\x99', L'\x9a', L'\x9b', L'\x9c', L'\x9d', L'\x9e', L'\x9f',
|
||||||
|
- L'\xa0', L'\xa1', L'\xa2', L'\xa3', L'\xa4', L'\xa5', L'\xa6', L'\xa7',
|
||||||
|
- L'\xa8', L'\xa9', L'\xaa', L'\xab', L'\xac', L'\xad', L'\xae', L'\xaf',
|
||||||
|
- L'\xb0', L'\xb1', L'\xb2', L'\xb3', L'\xb4', L'\xb5', L'\xb6', L'\xb7',
|
||||||
|
- L'\xb8', L'\xb9', L'\xba', L'\xbb', L'\xbc', L'\xbd', L'\xbe', L'\xbf',
|
||||||
|
- L'\xc0', L'\xc1', L'\xc2', L'\xc3', L'\xc4', L'\xc5', L'\xc6', L'\xc7',
|
||||||
|
- L'\xc8', L'\xc9', L'\xca', L'\xcb', L'\xcc', L'\xcd', L'\xce', L'\xcf',
|
||||||
|
- L'\xd0', L'\xd1', L'\xd2', L'\xd3', L'\xd4', L'\xd5', L'\xd6', L'\xd7',
|
||||||
|
- L'\xd8', L'\xd9', L'\xda', L'\xdb', L'\xdc', L'\xdd', L'\xde', L'\xdf',
|
||||||
|
- L'\xe0', L'\xe1', L'\xe2', L'\xe3', L'\xe4', L'\xe5', L'\xe6', L'\xe7',
|
||||||
|
- L'\xe8', L'\xe9', L'\xea', L'\xeb', L'\xec', L'\xed', L'\xee', L'\xef',
|
||||||
|
- L'\xf0', L'\xf1', L'\xf2', L'\xf3', L'\xf4', L'\xf5', L'\xf6', L'\xf7',
|
||||||
|
- L'\xf8', L'\xf9', L'\xfa', L'\xfb', L'\xfc', L'\xfd', L'\xfe', L'\xff'
|
||||||
|
-};
|
||||||
|
+#include "C-collate-seq.c"
|
||||||
|
|
||||||
|
const struct __locale_data _nl_C_LC_COLLATE attribute_hidden =
|
||||||
|
{
|
||||||
|
diff --git a/locale/programs/ld-collate.c b/locale/programs/ld-collate.c
|
||||||
|
index b6406b775d3a81ad..0f314e40c4305dea 100644
|
||||||
|
--- a/locale/programs/ld-collate.c
|
||||||
|
+++ b/locale/programs/ld-collate.c
|
||||||
|
@@ -24,6 +24,7 @@
|
||||||
|
#include <wchar.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
+#include <array_length.h>
|
||||||
|
|
||||||
|
#include "localedef.h"
|
||||||
|
#include "charmap.h"
|
||||||
|
@@ -195,6 +196,9 @@ struct name_list
|
||||||
|
/* The real definition of the struct for the LC_COLLATE locale. */
|
||||||
|
struct locale_collate_t
|
||||||
|
{
|
||||||
|
+ /* Does the locale use code points to compare the encoding? */
|
||||||
|
+ bool codepoint_collation;
|
||||||
|
+
|
||||||
|
int col_weight_max;
|
||||||
|
int cur_weight_max;
|
||||||
|
|
||||||
|
@@ -1510,6 +1514,7 @@ collate_startup (struct linereader *ldfile, struct localedef_t *locale,
|
||||||
|
obstack_init (&collate->mempool);
|
||||||
|
|
||||||
|
collate->col_weight_max = -1;
|
||||||
|
+ collate->codepoint_collation = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* Reuse the copy_locale's data structures. */
|
||||||
|
@@ -1568,6 +1573,10 @@ collate_finish (struct localedef_t *locale, const struct charmap_t *charmap)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* No data required. */
|
||||||
|
+ if (collate->codepoint_collation)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
/* If this assertion is hit change the type in `element_t'. */
|
||||||
|
assert (nrules <= sizeof (runp->used_in_level) * 8);
|
||||||
|
|
||||||
|
@@ -2092,6 +2101,10 @@ add_to_tablewc (uint32_t ch, struct element_t *runp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Include the C locale identity tables for _NL_COLLATE_COLLSEQMB and
|
||||||
|
+ _NL_COLLATE_COLLSEQWC. */
|
||||||
|
+#include "C-collate-seq.c"
|
||||||
|
+
|
||||||
|
void
|
||||||
|
collate_output (struct localedef_t *locale, const struct charmap_t *charmap,
|
||||||
|
const char *output_path)
|
||||||
|
@@ -2115,7 +2128,7 @@ collate_output (struct localedef_t *locale, const struct charmap_t *charmap,
|
||||||
|
add_locale_uint32 (&file, nrules);
|
||||||
|
|
||||||
|
/* If we have no LC_COLLATE data emit only the number of rules as zero. */
|
||||||
|
- if (collate == NULL)
|
||||||
|
+ if (collate == NULL || collate->codepoint_collation)
|
||||||
|
{
|
||||||
|
size_t idx;
|
||||||
|
for (idx = 1; idx < nelems; idx++)
|
||||||
|
@@ -2123,6 +2136,17 @@ collate_output (struct localedef_t *locale, const struct charmap_t *charmap,
|
||||||
|
/* The words have to be handled specially. */
|
||||||
|
if (idx == _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_SIZEMB))
|
||||||
|
add_locale_uint32 (&file, 0);
|
||||||
|
+ else if (idx == _NL_ITEM_INDEX (_NL_COLLATE_CODESET)
|
||||||
|
+ && collate != NULL)
|
||||||
|
+ /* A valid LC_COLLATE must have a code set name. */
|
||||||
|
+ add_locale_string (&file, charmap->code_set_name);
|
||||||
|
+ else if (idx == _NL_ITEM_INDEX (_NL_COLLATE_COLLSEQMB)
|
||||||
|
+ && collate != NULL)
|
||||||
|
+ add_locale_raw_data (&file, collseqmb, sizeof (collseqmb));
|
||||||
|
+ else if (idx == _NL_ITEM_INDEX (_NL_COLLATE_COLLSEQWC)
|
||||||
|
+ && collate != NULL)
|
||||||
|
+ add_locale_uint32_array (&file, collseqwc,
|
||||||
|
+ array_length (collseqwc));
|
||||||
|
else
|
||||||
|
add_locale_empty (&file);
|
||||||
|
}
|
||||||
|
@@ -2672,6 +2696,10 @@ collate_read (struct linereader *ldfile, struct localedef_t *result,
|
||||||
|
|
||||||
|
switch (nowtok)
|
||||||
|
{
|
||||||
|
+ case tok_codepoint_collation:
|
||||||
|
+ collate->codepoint_collation = true;
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
case tok_copy:
|
||||||
|
/* Allow copying other locales. */
|
||||||
|
now = lr_token (ldfile, charmap, result, NULL, verbose);
|
||||||
|
@@ -3742,9 +3770,11 @@ error while adding equivalent collating symbol"));
|
||||||
|
/* Next we assume `LC_COLLATE'. */
|
||||||
|
if (!ignore_content)
|
||||||
|
{
|
||||||
|
- if (state == 0 && copy_locale == NULL)
|
||||||
|
+ if (state == 0
|
||||||
|
+ && copy_locale == NULL
|
||||||
|
+ && !collate->codepoint_collation)
|
||||||
|
/* We must either see a copy statement or have
|
||||||
|
- ordering values. */
|
||||||
|
+ ordering values, or codepoint_collation. */
|
||||||
|
lr_error (ldfile,
|
||||||
|
_("%s: empty category description not allowed"),
|
||||||
|
"LC_COLLATE");
|
||||||
|
diff --git a/locale/programs/locfile-kw.gperf b/locale/programs/locfile-kw.gperf
|
||||||
|
index bcded15ddb4c44bb..2e59eb9ac014134b 100644
|
||||||
|
--- a/locale/programs/locfile-kw.gperf
|
||||||
|
+++ b/locale/programs/locfile-kw.gperf
|
||||||
|
@@ -54,6 +54,7 @@ translit_end, tok_translit_end, 0
|
||||||
|
translit_ignore, tok_translit_ignore, 0
|
||||||
|
default_missing, tok_default_missing, 0
|
||||||
|
LC_COLLATE, tok_lc_collate, 0
|
||||||
|
+codepoint_collation, tok_codepoint_collation, 0
|
||||||
|
coll_weight_max, tok_coll_weight_max, 0
|
||||||
|
section-symbol, tok_section_symbol, 0
|
||||||
|
collating-element, tok_collating_element, 0
|
||||||
|
diff --git a/locale/programs/locfile-kw.h b/locale/programs/locfile-kw.h
|
||||||
|
index bc1cb8f0845852ad..fe6335692bd422cd 100644
|
||||||
|
--- a/locale/programs/locfile-kw.h
|
||||||
|
+++ b/locale/programs/locfile-kw.h
|
||||||
|
@@ -54,7 +54,7 @@
|
||||||
|
#line 24 "locfile-kw.gperf"
|
||||||
|
struct keyword_t ;
|
||||||
|
|
||||||
|
-#define TOTAL_KEYWORDS 178
|
||||||
|
+#define TOTAL_KEYWORDS 179
|
||||||
|
#define MIN_WORD_LENGTH 3
|
||||||
|
#define MAX_WORD_LENGTH 22
|
||||||
|
#define MIN_HASH_VALUE 3
|
||||||
|
@@ -134,92 +134,92 @@ locfile_hash (register const char *str, register size_t len)
|
||||||
|
#line 31 "locfile-kw.gperf"
|
||||||
|
{"END", tok_end, 0},
|
||||||
|
{""}, {""},
|
||||||
|
-#line 70 "locfile-kw.gperf"
|
||||||
|
+#line 71 "locfile-kw.gperf"
|
||||||
|
{"IGNORE", tok_ignore, 0},
|
||||||
|
-#line 129 "locfile-kw.gperf"
|
||||||
|
+#line 130 "locfile-kw.gperf"
|
||||||
|
{"LC_TIME", tok_lc_time, 0},
|
||||||
|
#line 30 "locfile-kw.gperf"
|
||||||
|
{"LC_CTYPE", tok_lc_ctype, 0},
|
||||||
|
{""},
|
||||||
|
-#line 168 "locfile-kw.gperf"
|
||||||
|
+#line 169 "locfile-kw.gperf"
|
||||||
|
{"LC_ADDRESS", tok_lc_address, 0},
|
||||||
|
-#line 153 "locfile-kw.gperf"
|
||||||
|
+#line 154 "locfile-kw.gperf"
|
||||||
|
{"LC_MESSAGES", tok_lc_messages, 0},
|
||||||
|
-#line 161 "locfile-kw.gperf"
|
||||||
|
+#line 162 "locfile-kw.gperf"
|
||||||
|
{"LC_NAME", tok_lc_name, 0},
|
||||||
|
-#line 158 "locfile-kw.gperf"
|
||||||
|
+#line 159 "locfile-kw.gperf"
|
||||||
|
{"LC_PAPER", tok_lc_paper, 0},
|
||||||
|
-#line 186 "locfile-kw.gperf"
|
||||||
|
+#line 187 "locfile-kw.gperf"
|
||||||
|
{"LC_MEASUREMENT", tok_lc_measurement, 0},
|
||||||
|
#line 56 "locfile-kw.gperf"
|
||||||
|
{"LC_COLLATE", tok_lc_collate, 0},
|
||||||
|
{""},
|
||||||
|
-#line 188 "locfile-kw.gperf"
|
||||||
|
+#line 189 "locfile-kw.gperf"
|
||||||
|
{"LC_IDENTIFICATION", tok_lc_identification, 0},
|
||||||
|
-#line 201 "locfile-kw.gperf"
|
||||||
|
+#line 202 "locfile-kw.gperf"
|
||||||
|
{"revision", tok_revision, 0},
|
||||||
|
-#line 69 "locfile-kw.gperf"
|
||||||
|
+#line 70 "locfile-kw.gperf"
|
||||||
|
{"UNDEFINED", tok_undefined, 0},
|
||||||
|
-#line 125 "locfile-kw.gperf"
|
||||||
|
+#line 126 "locfile-kw.gperf"
|
||||||
|
{"LC_NUMERIC", tok_lc_numeric, 0},
|
||||||
|
-#line 82 "locfile-kw.gperf"
|
||||||
|
+#line 83 "locfile-kw.gperf"
|
||||||
|
{"LC_MONETARY", tok_lc_monetary, 0},
|
||||||
|
-#line 181 "locfile-kw.gperf"
|
||||||
|
+#line 182 "locfile-kw.gperf"
|
||||||
|
{"LC_TELEPHONE", tok_lc_telephone, 0},
|
||||||
|
{""}, {""}, {""},
|
||||||
|
-#line 75 "locfile-kw.gperf"
|
||||||
|
+#line 76 "locfile-kw.gperf"
|
||||||
|
{"define", tok_define, 0},
|
||||||
|
-#line 154 "locfile-kw.gperf"
|
||||||
|
+#line 155 "locfile-kw.gperf"
|
||||||
|
{"yesexpr", tok_yesexpr, 0},
|
||||||
|
-#line 141 "locfile-kw.gperf"
|
||||||
|
+#line 142 "locfile-kw.gperf"
|
||||||
|
{"era_year", tok_era_year, 0},
|
||||||
|
{""},
|
||||||
|
#line 54 "locfile-kw.gperf"
|
||||||
|
{"translit_ignore", tok_translit_ignore, 0},
|
||||||
|
-#line 156 "locfile-kw.gperf"
|
||||||
|
+#line 157 "locfile-kw.gperf"
|
||||||
|
{"yesstr", tok_yesstr, 0},
|
||||||
|
{""},
|
||||||
|
-#line 89 "locfile-kw.gperf"
|
||||||
|
+#line 90 "locfile-kw.gperf"
|
||||||
|
{"negative_sign", tok_negative_sign, 0},
|
||||||
|
{""},
|
||||||
|
-#line 137 "locfile-kw.gperf"
|
||||||
|
+#line 138 "locfile-kw.gperf"
|
||||||
|
{"t_fmt", tok_t_fmt, 0},
|
||||||
|
-#line 159 "locfile-kw.gperf"
|
||||||
|
+#line 160 "locfile-kw.gperf"
|
||||||
|
{"height", tok_height, 0},
|
||||||
|
{""}, {""},
|
||||||
|
#line 52 "locfile-kw.gperf"
|
||||||
|
{"translit_start", tok_translit_start, 0},
|
||||||
|
-#line 136 "locfile-kw.gperf"
|
||||||
|
+#line 137 "locfile-kw.gperf"
|
||||||
|
{"d_fmt", tok_d_fmt, 0},
|
||||||
|
{""},
|
||||||
|
#line 53 "locfile-kw.gperf"
|
||||||
|
{"translit_end", tok_translit_end, 0},
|
||||||
|
-#line 94 "locfile-kw.gperf"
|
||||||
|
+#line 95 "locfile-kw.gperf"
|
||||||
|
{"n_cs_precedes", tok_n_cs_precedes, 0},
|
||||||
|
-#line 144 "locfile-kw.gperf"
|
||||||
|
+#line 145 "locfile-kw.gperf"
|
||||||
|
{"era_t_fmt", tok_era_t_fmt, 0},
|
||||||
|
#line 39 "locfile-kw.gperf"
|
||||||
|
{"space", tok_space, 0},
|
||||||
|
-#line 72 "locfile-kw.gperf"
|
||||||
|
- {"reorder-end", tok_reorder_end, 0},
|
||||||
|
#line 73 "locfile-kw.gperf"
|
||||||
|
+ {"reorder-end", tok_reorder_end, 0},
|
||||||
|
+#line 74 "locfile-kw.gperf"
|
||||||
|
{"reorder-sections-after", tok_reorder_sections_after, 0},
|
||||||
|
{""},
|
||||||
|
-#line 142 "locfile-kw.gperf"
|
||||||
|
+#line 143 "locfile-kw.gperf"
|
||||||
|
{"era_d_fmt", tok_era_d_fmt, 0},
|
||||||
|
-#line 189 "locfile-kw.gperf"
|
||||||
|
+#line 190 "locfile-kw.gperf"
|
||||||
|
{"title", tok_title, 0},
|
||||||
|
{""}, {""},
|
||||||
|
-#line 149 "locfile-kw.gperf"
|
||||||
|
+#line 150 "locfile-kw.gperf"
|
||||||
|
{"timezone", tok_timezone, 0},
|
||||||
|
{""},
|
||||||
|
-#line 74 "locfile-kw.gperf"
|
||||||
|
+#line 75 "locfile-kw.gperf"
|
||||||
|
{"reorder-sections-end", tok_reorder_sections_end, 0},
|
||||||
|
{""}, {""}, {""},
|
||||||
|
-#line 95 "locfile-kw.gperf"
|
||||||
|
+#line 96 "locfile-kw.gperf"
|
||||||
|
{"n_sep_by_space", tok_n_sep_by_space, 0},
|
||||||
|
{""}, {""},
|
||||||
|
-#line 100 "locfile-kw.gperf"
|
||||||
|
+#line 101 "locfile-kw.gperf"
|
||||||
|
{"int_n_cs_precedes", tok_int_n_cs_precedes, 0},
|
||||||
|
{""}, {""}, {""},
|
||||||
|
#line 26 "locfile-kw.gperf"
|
||||||
|
@@ -233,147 +233,147 @@ locfile_hash (register const char *str, register size_t len)
|
||||||
|
{"print", tok_print, 0},
|
||||||
|
#line 44 "locfile-kw.gperf"
|
||||||
|
{"xdigit", tok_xdigit, 0},
|
||||||
|
-#line 110 "locfile-kw.gperf"
|
||||||
|
+#line 111 "locfile-kw.gperf"
|
||||||
|
{"duo_n_cs_precedes", tok_duo_n_cs_precedes, 0},
|
||||||
|
-#line 127 "locfile-kw.gperf"
|
||||||
|
+#line 128 "locfile-kw.gperf"
|
||||||
|
{"thousands_sep", tok_thousands_sep, 0},
|
||||||
|
-#line 197 "locfile-kw.gperf"
|
||||||
|
+#line 198 "locfile-kw.gperf"
|
||||||
|
{"territory", tok_territory, 0},
|
||||||
|
#line 36 "locfile-kw.gperf"
|
||||||
|
{"digit", tok_digit, 0},
|
||||||
|
{""}, {""},
|
||||||
|
-#line 92 "locfile-kw.gperf"
|
||||||
|
+#line 93 "locfile-kw.gperf"
|
||||||
|
{"p_cs_precedes", tok_p_cs_precedes, 0},
|
||||||
|
{""}, {""},
|
||||||
|
-#line 62 "locfile-kw.gperf"
|
||||||
|
+#line 63 "locfile-kw.gperf"
|
||||||
|
{"script", tok_script, 0},
|
||||||
|
#line 29 "locfile-kw.gperf"
|
||||||
|
{"include", tok_include, 0},
|
||||||
|
{""},
|
||||||
|
-#line 78 "locfile-kw.gperf"
|
||||||
|
+#line 79 "locfile-kw.gperf"
|
||||||
|
{"else", tok_else, 0},
|
||||||
|
-#line 184 "locfile-kw.gperf"
|
||||||
|
+#line 185 "locfile-kw.gperf"
|
||||||
|
{"int_select", tok_int_select, 0},
|
||||||
|
{""}, {""}, {""},
|
||||||
|
-#line 132 "locfile-kw.gperf"
|
||||||
|
+#line 133 "locfile-kw.gperf"
|
||||||
|
{"week", tok_week, 0},
|
||||||
|
#line 33 "locfile-kw.gperf"
|
||||||
|
{"upper", tok_upper, 0},
|
||||||
|
{""}, {""},
|
||||||
|
-#line 194 "locfile-kw.gperf"
|
||||||
|
+#line 195 "locfile-kw.gperf"
|
||||||
|
{"tel", tok_tel, 0},
|
||||||
|
-#line 93 "locfile-kw.gperf"
|
||||||
|
+#line 94 "locfile-kw.gperf"
|
||||||
|
{"p_sep_by_space", tok_p_sep_by_space, 0},
|
||||||
|
-#line 160 "locfile-kw.gperf"
|
||||||
|
+#line 161 "locfile-kw.gperf"
|
||||||
|
{"width", tok_width, 0},
|
||||||
|
{""},
|
||||||
|
-#line 98 "locfile-kw.gperf"
|
||||||
|
+#line 99 "locfile-kw.gperf"
|
||||||
|
{"int_p_cs_precedes", tok_int_p_cs_precedes, 0},
|
||||||
|
{""}, {""},
|
||||||
|
#line 41 "locfile-kw.gperf"
|
||||||
|
{"punct", tok_punct, 0},
|
||||||
|
{""}, {""},
|
||||||
|
-#line 101 "locfile-kw.gperf"
|
||||||
|
+#line 102 "locfile-kw.gperf"
|
||||||
|
{"int_n_sep_by_space", tok_int_n_sep_by_space, 0},
|
||||||
|
{""}, {""}, {""},
|
||||||
|
-#line 108 "locfile-kw.gperf"
|
||||||
|
+#line 109 "locfile-kw.gperf"
|
||||||
|
{"duo_p_cs_precedes", tok_duo_p_cs_precedes, 0},
|
||||||
|
#line 48 "locfile-kw.gperf"
|
||||||
|
{"charconv", tok_charconv, 0},
|
||||||
|
{""},
|
||||||
|
#line 47 "locfile-kw.gperf"
|
||||||
|
{"class", tok_class, 0},
|
||||||
|
-#line 114 "locfile-kw.gperf"
|
||||||
|
- {"duo_int_n_cs_precedes", tok_duo_int_n_cs_precedes, 0},
|
||||||
|
#line 115 "locfile-kw.gperf"
|
||||||
|
+ {"duo_int_n_cs_precedes", tok_duo_int_n_cs_precedes, 0},
|
||||||
|
+#line 116 "locfile-kw.gperf"
|
||||||
|
{"duo_int_n_sep_by_space", tok_duo_int_n_sep_by_space, 0},
|
||||||
|
-#line 111 "locfile-kw.gperf"
|
||||||
|
+#line 112 "locfile-kw.gperf"
|
||||||
|
{"duo_n_sep_by_space", tok_duo_n_sep_by_space, 0},
|
||||||
|
-#line 119 "locfile-kw.gperf"
|
||||||
|
+#line 120 "locfile-kw.gperf"
|
||||||
|
{"duo_int_n_sign_posn", tok_duo_int_n_sign_posn, 0},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
{""}, {""}, {""}, {""}, {""},
|
||||||
|
-#line 58 "locfile-kw.gperf"
|
||||||
|
+#line 59 "locfile-kw.gperf"
|
||||||
|
{"section-symbol", tok_section_symbol, 0},
|
||||||
|
-#line 185 "locfile-kw.gperf"
|
||||||
|
+#line 186 "locfile-kw.gperf"
|
||||||
|
{"int_prefix", tok_int_prefix, 0},
|
||||||
|
{""}, {""}, {""}, {""},
|
||||||
|
#line 42 "locfile-kw.gperf"
|
||||||
|
{"graph", tok_graph, 0},
|
||||||
|
{""}, {""},
|
||||||
|
-#line 99 "locfile-kw.gperf"
|
||||||
|
+#line 100 "locfile-kw.gperf"
|
||||||
|
{"int_p_sep_by_space", tok_int_p_sep_by_space, 0},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
-#line 112 "locfile-kw.gperf"
|
||||||
|
- {"duo_int_p_cs_precedes", tok_duo_int_p_cs_precedes, 0},
|
||||||
|
#line 113 "locfile-kw.gperf"
|
||||||
|
+ {"duo_int_p_cs_precedes", tok_duo_int_p_cs_precedes, 0},
|
||||||
|
+#line 114 "locfile-kw.gperf"
|
||||||
|
{"duo_int_p_sep_by_space", tok_duo_int_p_sep_by_space, 0},
|
||||||
|
-#line 109 "locfile-kw.gperf"
|
||||||
|
+#line 110 "locfile-kw.gperf"
|
||||||
|
{"duo_p_sep_by_space", tok_duo_p_sep_by_space, 0},
|
||||||
|
-#line 118 "locfile-kw.gperf"
|
||||||
|
+#line 119 "locfile-kw.gperf"
|
||||||
|
{"duo_int_p_sign_posn", tok_duo_int_p_sign_posn, 0},
|
||||||
|
-#line 157 "locfile-kw.gperf"
|
||||||
|
+#line 158 "locfile-kw.gperf"
|
||||||
|
{"nostr", tok_nostr, 0},
|
||||||
|
{""}, {""},
|
||||||
|
-#line 140 "locfile-kw.gperf"
|
||||||
|
+#line 141 "locfile-kw.gperf"
|
||||||
|
{"era", tok_era, 0},
|
||||||
|
{""},
|
||||||
|
-#line 84 "locfile-kw.gperf"
|
||||||
|
+#line 85 "locfile-kw.gperf"
|
||||||
|
{"currency_symbol", tok_currency_symbol, 0},
|
||||||
|
{""},
|
||||||
|
-#line 167 "locfile-kw.gperf"
|
||||||
|
+#line 168 "locfile-kw.gperf"
|
||||||
|
{"name_ms", tok_name_ms, 0},
|
||||||
|
-#line 165 "locfile-kw.gperf"
|
||||||
|
- {"name_mrs", tok_name_mrs, 0},
|
||||||
|
#line 166 "locfile-kw.gperf"
|
||||||
|
+ {"name_mrs", tok_name_mrs, 0},
|
||||||
|
+#line 167 "locfile-kw.gperf"
|
||||||
|
{"name_miss", tok_name_miss, 0},
|
||||||
|
-#line 83 "locfile-kw.gperf"
|
||||||
|
+#line 84 "locfile-kw.gperf"
|
||||||
|
{"int_curr_symbol", tok_int_curr_symbol, 0},
|
||||||
|
-#line 190 "locfile-kw.gperf"
|
||||||
|
+#line 191 "locfile-kw.gperf"
|
||||||
|
{"source", tok_source, 0},
|
||||||
|
-#line 164 "locfile-kw.gperf"
|
||||||
|
+#line 165 "locfile-kw.gperf"
|
||||||
|
{"name_mr", tok_name_mr, 0},
|
||||||
|
-#line 163 "locfile-kw.gperf"
|
||||||
|
+#line 164 "locfile-kw.gperf"
|
||||||
|
{"name_gen", tok_name_gen, 0},
|
||||||
|
-#line 202 "locfile-kw.gperf"
|
||||||
|
+#line 203 "locfile-kw.gperf"
|
||||||
|
{"date", tok_date, 0},
|
||||||
|
{""}, {""},
|
||||||
|
-#line 191 "locfile-kw.gperf"
|
||||||
|
+#line 192 "locfile-kw.gperf"
|
||||||
|
{"address", tok_address, 0},
|
||||||
|
-#line 162 "locfile-kw.gperf"
|
||||||
|
+#line 163 "locfile-kw.gperf"
|
||||||
|
{"name_fmt", tok_name_fmt, 0},
|
||||||
|
#line 32 "locfile-kw.gperf"
|
||||||
|
{"copy", tok_copy, 0},
|
||||||
|
-#line 103 "locfile-kw.gperf"
|
||||||
|
+#line 104 "locfile-kw.gperf"
|
||||||
|
{"int_n_sign_posn", tok_int_n_sign_posn, 0},
|
||||||
|
{""}, {""},
|
||||||
|
-#line 131 "locfile-kw.gperf"
|
||||||
|
+#line 132 "locfile-kw.gperf"
|
||||||
|
{"day", tok_day, 0},
|
||||||
|
-#line 105 "locfile-kw.gperf"
|
||||||
|
+#line 106 "locfile-kw.gperf"
|
||||||
|
{"duo_currency_symbol", tok_duo_currency_symbol, 0},
|
||||||
|
{""}, {""}, {""},
|
||||||
|
-#line 150 "locfile-kw.gperf"
|
||||||
|
+#line 151 "locfile-kw.gperf"
|
||||||
|
{"date_fmt", tok_date_fmt, 0},
|
||||||
|
-#line 64 "locfile-kw.gperf"
|
||||||
|
+#line 65 "locfile-kw.gperf"
|
||||||
|
{"order_end", tok_order_end, 0},
|
||||||
|
-#line 117 "locfile-kw.gperf"
|
||||||
|
+#line 118 "locfile-kw.gperf"
|
||||||
|
{"duo_n_sign_posn", tok_duo_n_sign_posn, 0},
|
||||||
|
{""},
|
||||||
|
-#line 170 "locfile-kw.gperf"
|
||||||
|
+#line 171 "locfile-kw.gperf"
|
||||||
|
{"country_name", tok_country_name, 0},
|
||||||
|
-#line 71 "locfile-kw.gperf"
|
||||||
|
+#line 72 "locfile-kw.gperf"
|
||||||
|
{"reorder-after", tok_reorder_after, 0},
|
||||||
|
{""}, {""},
|
||||||
|
-#line 155 "locfile-kw.gperf"
|
||||||
|
+#line 156 "locfile-kw.gperf"
|
||||||
|
{"noexpr", tok_noexpr, 0},
|
||||||
|
#line 50 "locfile-kw.gperf"
|
||||||
|
{"tolower", tok_tolower, 0},
|
||||||
|
-#line 198 "locfile-kw.gperf"
|
||||||
|
+#line 199 "locfile-kw.gperf"
|
||||||
|
{"audience", tok_audience, 0},
|
||||||
|
{""}, {""}, {""},
|
||||||
|
#line 49 "locfile-kw.gperf"
|
||||||
|
{"toupper", tok_toupper, 0},
|
||||||
|
-#line 68 "locfile-kw.gperf"
|
||||||
|
+#line 69 "locfile-kw.gperf"
|
||||||
|
{"position", tok_position, 0},
|
||||||
|
{""},
|
||||||
|
#line 40 "locfile-kw.gperf"
|
||||||
|
@@ -381,196 +381,197 @@ locfile_hash (register const char *str, register size_t len)
|
||||||
|
{""},
|
||||||
|
#line 27 "locfile-kw.gperf"
|
||||||
|
{"comment_char", tok_comment_char, 0},
|
||||||
|
-#line 88 "locfile-kw.gperf"
|
||||||
|
+#line 89 "locfile-kw.gperf"
|
||||||
|
{"positive_sign", tok_positive_sign, 0},
|
||||||
|
{""}, {""}, {""}, {""},
|
||||||
|
-#line 61 "locfile-kw.gperf"
|
||||||
|
+#line 62 "locfile-kw.gperf"
|
||||||
|
{"symbol-equivalence", tok_symbol_equivalence, 0},
|
||||||
|
{""},
|
||||||
|
-#line 102 "locfile-kw.gperf"
|
||||||
|
+#line 103 "locfile-kw.gperf"
|
||||||
|
{"int_p_sign_posn", tok_int_p_sign_posn, 0},
|
||||||
|
-#line 175 "locfile-kw.gperf"
|
||||||
|
+#line 176 "locfile-kw.gperf"
|
||||||
|
{"country_car", tok_country_car, 0},
|
||||||
|
{""}, {""},
|
||||||
|
-#line 104 "locfile-kw.gperf"
|
||||||
|
+#line 105 "locfile-kw.gperf"
|
||||||
|
{"duo_int_curr_symbol", tok_duo_int_curr_symbol, 0},
|
||||||
|
{""}, {""},
|
||||||
|
-#line 135 "locfile-kw.gperf"
|
||||||
|
+#line 136 "locfile-kw.gperf"
|
||||||
|
{"d_t_fmt", tok_d_t_fmt, 0},
|
||||||
|
{""}, {""},
|
||||||
|
-#line 116 "locfile-kw.gperf"
|
||||||
|
+#line 117 "locfile-kw.gperf"
|
||||||
|
{"duo_p_sign_posn", tok_duo_p_sign_posn, 0},
|
||||||
|
-#line 187 "locfile-kw.gperf"
|
||||||
|
+#line 188 "locfile-kw.gperf"
|
||||||
|
{"measurement", tok_measurement, 0},
|
||||||
|
-#line 176 "locfile-kw.gperf"
|
||||||
|
+#line 177 "locfile-kw.gperf"
|
||||||
|
{"country_isbn", tok_country_isbn, 0},
|
||||||
|
#line 37 "locfile-kw.gperf"
|
||||||
|
{"outdigit", tok_outdigit, 0},
|
||||||
|
{""}, {""},
|
||||||
|
-#line 143 "locfile-kw.gperf"
|
||||||
|
+#line 144 "locfile-kw.gperf"
|
||||||
|
{"era_d_t_fmt", tok_era_d_t_fmt, 0},
|
||||||
|
{""}, {""}, {""},
|
||||||
|
#line 34 "locfile-kw.gperf"
|
||||||
|
{"lower", tok_lower, 0},
|
||||||
|
-#line 183 "locfile-kw.gperf"
|
||||||
|
+#line 184 "locfile-kw.gperf"
|
||||||
|
{"tel_dom_fmt", tok_tel_dom_fmt, 0},
|
||||||
|
-#line 171 "locfile-kw.gperf"
|
||||||
|
+#line 172 "locfile-kw.gperf"
|
||||||
|
{"country_post", tok_country_post, 0},
|
||||||
|
-#line 148 "locfile-kw.gperf"
|
||||||
|
+#line 149 "locfile-kw.gperf"
|
||||||
|
{"cal_direction", tok_cal_direction, 0},
|
||||||
|
- {""},
|
||||||
|
-#line 139 "locfile-kw.gperf"
|
||||||
|
+#line 57 "locfile-kw.gperf"
|
||||||
|
+ {"codepoint_collation", tok_codepoint_collation, 0},
|
||||||
|
+#line 140 "locfile-kw.gperf"
|
||||||
|
{"t_fmt_ampm", tok_t_fmt_ampm, 0},
|
||||||
|
-#line 91 "locfile-kw.gperf"
|
||||||
|
+#line 92 "locfile-kw.gperf"
|
||||||
|
{"frac_digits", tok_frac_digits, 0},
|
||||||
|
{""}, {""},
|
||||||
|
-#line 177 "locfile-kw.gperf"
|
||||||
|
+#line 178 "locfile-kw.gperf"
|
||||||
|
{"lang_name", tok_lang_name, 0},
|
||||||
|
-#line 90 "locfile-kw.gperf"
|
||||||
|
+#line 91 "locfile-kw.gperf"
|
||||||
|
{"int_frac_digits", tok_int_frac_digits, 0},
|
||||||
|
{""},
|
||||||
|
-#line 121 "locfile-kw.gperf"
|
||||||
|
+#line 122 "locfile-kw.gperf"
|
||||||
|
{"uno_valid_to", tok_uno_valid_to, 0},
|
||||||
|
-#line 126 "locfile-kw.gperf"
|
||||||
|
+#line 127 "locfile-kw.gperf"
|
||||||
|
{"decimal_point", tok_decimal_point, 0},
|
||||||
|
{""},
|
||||||
|
-#line 133 "locfile-kw.gperf"
|
||||||
|
+#line 134 "locfile-kw.gperf"
|
||||||
|
{"abmon", tok_abmon, 0},
|
||||||
|
{""}, {""}, {""}, {""},
|
||||||
|
-#line 107 "locfile-kw.gperf"
|
||||||
|
+#line 108 "locfile-kw.gperf"
|
||||||
|
{"duo_frac_digits", tok_duo_frac_digits, 0},
|
||||||
|
-#line 182 "locfile-kw.gperf"
|
||||||
|
+#line 183 "locfile-kw.gperf"
|
||||||
|
{"tel_int_fmt", tok_tel_int_fmt, 0},
|
||||||
|
-#line 123 "locfile-kw.gperf"
|
||||||
|
+#line 124 "locfile-kw.gperf"
|
||||||
|
{"duo_valid_to", tok_duo_valid_to, 0},
|
||||||
|
-#line 146 "locfile-kw.gperf"
|
||||||
|
+#line 147 "locfile-kw.gperf"
|
||||||
|
{"first_weekday", tok_first_weekday, 0},
|
||||||
|
{""},
|
||||||
|
-#line 130 "locfile-kw.gperf"
|
||||||
|
+#line 131 "locfile-kw.gperf"
|
||||||
|
{"abday", tok_abday, 0},
|
||||||
|
{""},
|
||||||
|
-#line 200 "locfile-kw.gperf"
|
||||||
|
+#line 201 "locfile-kw.gperf"
|
||||||
|
{"abbreviation", tok_abbreviation, 0},
|
||||||
|
-#line 147 "locfile-kw.gperf"
|
||||||
|
+#line 148 "locfile-kw.gperf"
|
||||||
|
{"first_workday", tok_first_workday, 0},
|
||||||
|
{""}, {""},
|
||||||
|
-#line 97 "locfile-kw.gperf"
|
||||||
|
+#line 98 "locfile-kw.gperf"
|
||||||
|
{"n_sign_posn", tok_n_sign_posn, 0},
|
||||||
|
{""}, {""}, {""},
|
||||||
|
-#line 145 "locfile-kw.gperf"
|
||||||
|
+#line 146 "locfile-kw.gperf"
|
||||||
|
{"alt_digits", tok_alt_digits, 0},
|
||||||
|
{""}, {""},
|
||||||
|
-#line 128 "locfile-kw.gperf"
|
||||||
|
+#line 129 "locfile-kw.gperf"
|
||||||
|
{"grouping", tok_grouping, 0},
|
||||||
|
{""},
|
||||||
|
#line 45 "locfile-kw.gperf"
|
||||||
|
{"blank", tok_blank, 0},
|
||||||
|
{""}, {""},
|
||||||
|
-#line 196 "locfile-kw.gperf"
|
||||||
|
+#line 197 "locfile-kw.gperf"
|
||||||
|
{"language", tok_language, 0},
|
||||||
|
-#line 120 "locfile-kw.gperf"
|
||||||
|
+#line 121 "locfile-kw.gperf"
|
||||||
|
{"uno_valid_from", tok_uno_valid_from, 0},
|
||||||
|
{""},
|
||||||
|
-#line 199 "locfile-kw.gperf"
|
||||||
|
+#line 200 "locfile-kw.gperf"
|
||||||
|
{"application", tok_application, 0},
|
||||||
|
{""},
|
||||||
|
-#line 80 "locfile-kw.gperf"
|
||||||
|
+#line 81 "locfile-kw.gperf"
|
||||||
|
{"elifndef", tok_elifndef, 0},
|
||||||
|
{""}, {""}, {""}, {""}, {""},
|
||||||
|
-#line 122 "locfile-kw.gperf"
|
||||||
|
+#line 123 "locfile-kw.gperf"
|
||||||
|
{"duo_valid_from", tok_duo_valid_from, 0},
|
||||||
|
-#line 57 "locfile-kw.gperf"
|
||||||
|
+#line 58 "locfile-kw.gperf"
|
||||||
|
{"coll_weight_max", tok_coll_weight_max, 0},
|
||||||
|
{""},
|
||||||
|
-#line 79 "locfile-kw.gperf"
|
||||||
|
+#line 80 "locfile-kw.gperf"
|
||||||
|
{"elifdef", tok_elifdef, 0},
|
||||||
|
-#line 67 "locfile-kw.gperf"
|
||||||
|
+#line 68 "locfile-kw.gperf"
|
||||||
|
{"backward", tok_backward, 0},
|
||||||
|
-#line 106 "locfile-kw.gperf"
|
||||||
|
+#line 107 "locfile-kw.gperf"
|
||||||
|
{"duo_int_frac_digits", tok_duo_int_frac_digits, 0},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
-#line 96 "locfile-kw.gperf"
|
||||||
|
+#line 97 "locfile-kw.gperf"
|
||||||
|
{"p_sign_posn", tok_p_sign_posn, 0},
|
||||||
|
{""},
|
||||||
|
-#line 203 "locfile-kw.gperf"
|
||||||
|
+#line 204 "locfile-kw.gperf"
|
||||||
|
{"category", tok_category, 0},
|
||||||
|
{""}, {""}, {""}, {""},
|
||||||
|
-#line 134 "locfile-kw.gperf"
|
||||||
|
+#line 135 "locfile-kw.gperf"
|
||||||
|
{"mon", tok_mon, 0},
|
||||||
|
{""},
|
||||||
|
-#line 124 "locfile-kw.gperf"
|
||||||
|
+#line 125 "locfile-kw.gperf"
|
||||||
|
{"conversion_rate", tok_conversion_rate, 0},
|
||||||
|
{""}, {""}, {""}, {""}, {""},
|
||||||
|
-#line 63 "locfile-kw.gperf"
|
||||||
|
+#line 64 "locfile-kw.gperf"
|
||||||
|
{"order_start", tok_order_start, 0},
|
||||||
|
{""}, {""}, {""}, {""}, {""},
|
||||||
|
-#line 178 "locfile-kw.gperf"
|
||||||
|
+#line 179 "locfile-kw.gperf"
|
||||||
|
{"lang_ab", tok_lang_ab, 0},
|
||||||
|
-#line 180 "locfile-kw.gperf"
|
||||||
|
+#line 181 "locfile-kw.gperf"
|
||||||
|
{"lang_lib", tok_lang_lib, 0},
|
||||||
|
{""}, {""}, {""},
|
||||||
|
-#line 192 "locfile-kw.gperf"
|
||||||
|
+#line 193 "locfile-kw.gperf"
|
||||||
|
{"contact", tok_contact, 0},
|
||||||
|
{""}, {""}, {""},
|
||||||
|
-#line 173 "locfile-kw.gperf"
|
||||||
|
+#line 174 "locfile-kw.gperf"
|
||||||
|
{"country_ab3", tok_country_ab3, 0},
|
||||||
|
{""}, {""}, {""},
|
||||||
|
-#line 193 "locfile-kw.gperf"
|
||||||
|
+#line 194 "locfile-kw.gperf"
|
||||||
|
{"email", tok_email, 0},
|
||||||
|
-#line 172 "locfile-kw.gperf"
|
||||||
|
+#line 173 "locfile-kw.gperf"
|
||||||
|
{"country_ab2", tok_country_ab2, 0},
|
||||||
|
{""}, {""}, {""},
|
||||||
|
#line 55 "locfile-kw.gperf"
|
||||||
|
{"default_missing", tok_default_missing, 0},
|
||||||
|
{""}, {""},
|
||||||
|
-#line 195 "locfile-kw.gperf"
|
||||||
|
+#line 196 "locfile-kw.gperf"
|
||||||
|
{"fax", tok_fax, 0},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
-#line 174 "locfile-kw.gperf"
|
||||||
|
+#line 175 "locfile-kw.gperf"
|
||||||
|
{"country_num", tok_country_num, 0},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
#line 51 "locfile-kw.gperf"
|
||||||
|
{"map", tok_map, 0},
|
||||||
|
-#line 65 "locfile-kw.gperf"
|
||||||
|
+#line 66 "locfile-kw.gperf"
|
||||||
|
{"from", tok_from, 0},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
-#line 86 "locfile-kw.gperf"
|
||||||
|
+#line 87 "locfile-kw.gperf"
|
||||||
|
{"mon_thousands_sep", tok_mon_thousands_sep, 0},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
{""}, {""}, {""},
|
||||||
|
-#line 81 "locfile-kw.gperf"
|
||||||
|
+#line 82 "locfile-kw.gperf"
|
||||||
|
{"endif", tok_endif, 0},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
-#line 151 "locfile-kw.gperf"
|
||||||
|
+#line 152 "locfile-kw.gperf"
|
||||||
|
{"alt_mon", tok_alt_mon, 0},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
-#line 76 "locfile-kw.gperf"
|
||||||
|
+#line 77 "locfile-kw.gperf"
|
||||||
|
{"undef", tok_undef, 0},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
-#line 59 "locfile-kw.gperf"
|
||||||
|
+#line 60 "locfile-kw.gperf"
|
||||||
|
{"collating-element", tok_collating_element, 0},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
-#line 152 "locfile-kw.gperf"
|
||||||
|
+#line 153 "locfile-kw.gperf"
|
||||||
|
{"ab_alt_mon", tok_ab_alt_mon, 0},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
-#line 66 "locfile-kw.gperf"
|
||||||
|
+#line 67 "locfile-kw.gperf"
|
||||||
|
{"forward", tok_forward, 0},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
{""}, {""}, {""}, {""}, {""},
|
||||||
|
-#line 85 "locfile-kw.gperf"
|
||||||
|
+#line 86 "locfile-kw.gperf"
|
||||||
|
{"mon_decimal_point", tok_mon_decimal_point, 0},
|
||||||
|
{""}, {""},
|
||||||
|
-#line 169 "locfile-kw.gperf"
|
||||||
|
+#line 170 "locfile-kw.gperf"
|
||||||
|
{"postal_fmt", tok_postal_fmt, 0},
|
||||||
|
{""}, {""}, {""}, {""}, {""},
|
||||||
|
-#line 60 "locfile-kw.gperf"
|
||||||
|
+#line 61 "locfile-kw.gperf"
|
||||||
|
{"collating-symbol", tok_collating_symbol, 0},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
@@ -583,15 +584,15 @@ locfile_hash (register const char *str, register size_t len)
|
||||||
|
#line 38 "locfile-kw.gperf"
|
||||||
|
{"alnum", tok_alnum, 0},
|
||||||
|
{""},
|
||||||
|
-#line 87 "locfile-kw.gperf"
|
||||||
|
+#line 88 "locfile-kw.gperf"
|
||||||
|
{"mon_grouping", tok_mon_grouping, 0},
|
||||||
|
{""},
|
||||||
|
-#line 179 "locfile-kw.gperf"
|
||||||
|
+#line 180 "locfile-kw.gperf"
|
||||||
|
{"lang_term", tok_lang_term, 0},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
-#line 77 "locfile-kw.gperf"
|
||||||
|
+#line 78 "locfile-kw.gperf"
|
||||||
|
{"ifdef", tok_ifdef, 0},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
@@ -599,7 +600,7 @@ locfile_hash (register const char *str, register size_t len)
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
{""}, {""}, {""}, {""},
|
||||||
|
-#line 138 "locfile-kw.gperf"
|
||||||
|
+#line 139 "locfile-kw.gperf"
|
||||||
|
{"am_pm", tok_am_pm, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
diff --git a/locale/programs/locfile-token.h b/locale/programs/locfile-token.h
|
||||||
|
index 414ad3076223e971..f57d594e8d25c06f 100644
|
||||||
|
--- a/locale/programs/locfile-token.h
|
||||||
|
+++ b/locale/programs/locfile-token.h
|
||||||
|
@@ -91,6 +91,7 @@ enum token_t
|
||||||
|
tok_translit_ignore,
|
||||||
|
tok_default_missing,
|
||||||
|
tok_lc_collate,
|
||||||
|
+ tok_codepoint_collation,
|
||||||
|
tok_coll_weight_max,
|
||||||
|
tok_section_symbol,
|
||||||
|
tok_collating_element,
|
1437
SOURCES/glibc-c-utf8-locale-2.patch
Normal file
1437
SOURCES/glibc-c-utf8-locale-2.patch
Normal file
File diff suppressed because it is too large
Load Diff
65
SOURCES/glibc-c-utf8-locale-3.patch
Normal file
65
SOURCES/glibc-c-utf8-locale-3.patch
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
commit 1d8e3a2c6636cf0b1b8fa2f869cef6ec10726933
|
||||||
|
Author: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
Date: Mon Jan 31 00:34:41 2022 -0500
|
||||||
|
|
||||||
|
localedef: Fix handling of empty mon_decimal_point (Bug 28847)
|
||||||
|
|
||||||
|
The handling of mon_decimal_point is incorrect when it comes to
|
||||||
|
handling the empty "" value. The existing parser in monetary_read()
|
||||||
|
will correctly handle setting the non-wide-character value and the
|
||||||
|
wide-character value e.g. STR_ELEM_WC(mon_decimal_point) if they are
|
||||||
|
set in the locale definition. However, in monetary_finish() we have
|
||||||
|
conflicting TEST_ELEM() which sets a default value (if the locale
|
||||||
|
definition doesn't include one), and subsequent code which looks for
|
||||||
|
mon_decimal_point to be NULL to issue a specific error message and set
|
||||||
|
the defaults. The latter is unused because TEST_ELEM() always sets a
|
||||||
|
default. The simplest solution is to remove the TEST_ELEM() check,
|
||||||
|
and allow the existing check to look to see if mon_decimal_point is
|
||||||
|
NULL and set an appropriate default. The final fix is to move the
|
||||||
|
setting of mon_decimal_point_wc so it occurs only when
|
||||||
|
mon_decimal_point is being set to a default, keeping both values
|
||||||
|
consistent. There is no way to tell the difference between
|
||||||
|
mon_decimal_point_wc having been set to the empty string and not
|
||||||
|
having been defined at all, for that distinction we must use
|
||||||
|
mon_decimal_point being NULL or "", and so we must logically set
|
||||||
|
the default together with mon_decimal_point.
|
||||||
|
|
||||||
|
Lastly, there are more fixes similar to this that could be made to
|
||||||
|
ld-monetary.c, but we avoid that in order to fix just the code
|
||||||
|
required for mon_decimal_point, which impacts the ability for C.UTF-8
|
||||||
|
to set mon_decimal_point to "", since without this fix we end up with
|
||||||
|
an inconsistent setting of mon_decimal_point set to "", but
|
||||||
|
mon_decimal_point_wc set to "." which is incorrect.
|
||||||
|
|
||||||
|
Tested on x86_64 and i686 without regression.
|
||||||
|
Reviewed-by: Florian Weimer <fweimer@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/locale/programs/ld-monetary.c b/locale/programs/ld-monetary.c
|
||||||
|
index e1e45a3409123bf4..9b9a55bb4766dfcf 100644
|
||||||
|
--- a/locale/programs/ld-monetary.c
|
||||||
|
+++ b/locale/programs/ld-monetary.c
|
||||||
|
@@ -208,7 +208,6 @@ No definition for %s category found"), "LC_MONETARY");
|
||||||
|
|
||||||
|
TEST_ELEM (int_curr_symbol, "");
|
||||||
|
TEST_ELEM (currency_symbol, "");
|
||||||
|
- TEST_ELEM (mon_decimal_point, ".");
|
||||||
|
TEST_ELEM (mon_thousands_sep, "");
|
||||||
|
TEST_ELEM (positive_sign, "");
|
||||||
|
TEST_ELEM (negative_sign, "");
|
||||||
|
@@ -258,6 +257,7 @@ not correspond to a valid name in ISO 4217 [--no-warnings=intcurrsym]"),
|
||||||
|
record_error (0, 0, _("%s: field `%s' not defined"),
|
||||||
|
"LC_MONETARY", "mon_decimal_point");
|
||||||
|
monetary->mon_decimal_point = ".";
|
||||||
|
+ monetary->mon_decimal_point_wc = L'.';
|
||||||
|
}
|
||||||
|
else if (monetary->mon_decimal_point[0] == '\0' && ! be_quiet && ! nothing)
|
||||||
|
{
|
||||||
|
@@ -265,8 +265,6 @@ not correspond to a valid name in ISO 4217 [--no-warnings=intcurrsym]"),
|
||||||
|
%s: value for field `%s' must not be an empty string"),
|
||||||
|
"LC_MONETARY", "mon_decimal_point");
|
||||||
|
}
|
||||||
|
- if (monetary->mon_decimal_point_wc == L'\0')
|
||||||
|
- monetary->mon_decimal_point_wc = L'.';
|
||||||
|
|
||||||
|
if (monetary->mon_grouping_len == 0)
|
||||||
|
{
|
734
SOURCES/glibc-c-utf8-locale-4.patch
Normal file
734
SOURCES/glibc-c-utf8-locale-4.patch
Normal file
@ -0,0 +1,734 @@
|
|||||||
|
commit de82cb0da4b8fa5b3d56c457438d2568c67ab1b1
|
||||||
|
Author: Joseph Myers <joseph@codesourcery.com>
|
||||||
|
Date: Tue Oct 12 13:48:39 2021 +0000
|
||||||
|
|
||||||
|
Add TEST_COMPARE_STRING_WIDE to support/check.h
|
||||||
|
|
||||||
|
I'd like to be able to test narrow and wide string interfaces, with
|
||||||
|
the narrow string tests using TEST_COMPARE_STRING and the wide string
|
||||||
|
tests using something analogous (possibly generated using macros from
|
||||||
|
a common test template for both the narrow and wide string tests where
|
||||||
|
appropriate).
|
||||||
|
|
||||||
|
Add such a TEST_COMPARE_STRING_WIDE, along with functions
|
||||||
|
support_quote_blob_wide and support_test_compare_string_wide that it
|
||||||
|
builds on. Those functions are built using macros from common
|
||||||
|
templates shared by the narrow and wide string implementations, though
|
||||||
|
I didn't do that for the tests of test functions. In
|
||||||
|
support_quote_blob_wide, I chose to use the \x{} delimited escape
|
||||||
|
sequence syntax proposed for C2X in N2785, rather than e.g. trying to
|
||||||
|
generate the end of a string and the start of a new string when
|
||||||
|
ambiguity would result from undelimited \x (when the next character
|
||||||
|
after such an escape sequence is valid hex) or forcing an escape
|
||||||
|
sequence to be used for the next character in the case of such
|
||||||
|
ambiguity.
|
||||||
|
|
||||||
|
Tested for x86_64.
|
||||||
|
|
||||||
|
diff --git a/support/Makefile b/support/Makefile
|
||||||
|
index 75bad6715ac3d08c..3c941e1ba9e29aa4 100644
|
||||||
|
--- a/support/Makefile
|
||||||
|
+++ b/support/Makefile
|
||||||
|
@@ -70,6 +70,7 @@ libsupport-routines = \
|
||||||
|
support_openpty \
|
||||||
|
support_paths \
|
||||||
|
support_quote_blob \
|
||||||
|
+ support_quote_blob_wide \
|
||||||
|
support_quote_string \
|
||||||
|
support_record_failure \
|
||||||
|
support_run_diff \
|
||||||
|
@@ -83,6 +84,7 @@ libsupport-routines = \
|
||||||
|
support_test_compare_blob \
|
||||||
|
support_test_compare_failure \
|
||||||
|
support_test_compare_string \
|
||||||
|
+ support_test_compare_string_wide \
|
||||||
|
support_test_main \
|
||||||
|
support_test_verify_impl \
|
||||||
|
support_wait_for_thread_exit \
|
||||||
|
@@ -275,11 +277,13 @@ tests = \
|
||||||
|
tst-support-open-dev-null-range \
|
||||||
|
tst-support-process_state \
|
||||||
|
tst-support_quote_blob \
|
||||||
|
+ tst-support_quote_blob_wide \
|
||||||
|
tst-support_quote_string \
|
||||||
|
tst-support_record_failure \
|
||||||
|
tst-test_compare \
|
||||||
|
tst-test_compare_blob \
|
||||||
|
tst-test_compare_string \
|
||||||
|
+ tst-test_compare_string_wide \
|
||||||
|
tst-timespec \
|
||||||
|
tst-xreadlink \
|
||||||
|
tst-xsigstack \
|
||||||
|
diff --git a/support/check.h b/support/check.h
|
||||||
|
index 83662b2d10c8cf58..9b1844352f32513a 100644
|
||||||
|
--- a/support/check.h
|
||||||
|
+++ b/support/check.h
|
||||||
|
@@ -20,6 +20,7 @@
|
||||||
|
#define SUPPORT_CHECK_H
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
+#include <stddef.h>
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
@@ -171,11 +172,25 @@ void support_test_compare_blob (const void *left,
|
||||||
|
(support_test_compare_string (left, right, __FILE__, __LINE__, \
|
||||||
|
#left, #right))
|
||||||
|
|
||||||
|
+/* Compare the wide strings LEFT and RIGHT and report a test failure
|
||||||
|
+ if they are different. Also report failure if one of the arguments
|
||||||
|
+ is a null pointer and the other is not. The strings should be
|
||||||
|
+ reasonably short because on mismatch, both are printed. */
|
||||||
|
+#define TEST_COMPARE_STRING_WIDE(left, right) \
|
||||||
|
+ (support_test_compare_string_wide (left, right, __FILE__, __LINE__, \
|
||||||
|
+ #left, #right))
|
||||||
|
+
|
||||||
|
void support_test_compare_string (const char *left, const char *right,
|
||||||
|
const char *file, int line,
|
||||||
|
const char *left_expr,
|
||||||
|
const char *right_expr);
|
||||||
|
|
||||||
|
+void support_test_compare_string_wide (const wchar_t *left,
|
||||||
|
+ const wchar_t *right,
|
||||||
|
+ const char *file, int line,
|
||||||
|
+ const char *left_expr,
|
||||||
|
+ const char *right_expr);
|
||||||
|
+
|
||||||
|
/* Internal function called by the test driver. */
|
||||||
|
int support_report_failure (int status)
|
||||||
|
__attribute__ ((weak, warn_unused_result));
|
||||||
|
diff --git a/support/support.h b/support/support.h
|
||||||
|
index c219e0d9d1aef046..29d56c7c891ee34b 100644
|
||||||
|
--- a/support/support.h
|
||||||
|
+++ b/support/support.h
|
||||||
|
@@ -73,6 +73,12 @@ void support_write_file_string (const char *path, const char *contents);
|
||||||
|
the result). */
|
||||||
|
char *support_quote_blob (const void *blob, size_t length);
|
||||||
|
|
||||||
|
+/* Quote the contents of the wide character array starting at BLOB, of
|
||||||
|
+ LENGTH wide characters, in such a way that the result string can be
|
||||||
|
+ included in a C wide string literal (in single/double quotes,
|
||||||
|
+ without putting the quotes into the result). */
|
||||||
|
+char *support_quote_blob_wide (const void *blob, size_t length);
|
||||||
|
+
|
||||||
|
/* Quote the contents of the string, in such a way that the result
|
||||||
|
string can be included in a C literal (in single/double quotes,
|
||||||
|
without putting the quotes into the result). */
|
||||||
|
diff --git a/support/support_quote_blob.c b/support/support_quote_blob.c
|
||||||
|
index b5e70125f13eb081..611980c9a2108670 100644
|
||||||
|
--- a/support/support_quote_blob.c
|
||||||
|
+++ b/support/support_quote_blob.c
|
||||||
|
@@ -1,4 +1,4 @@
|
||||||
|
-/* Quote a blob so that it can be used in C literals.
|
||||||
|
+/* Quote a narrow string blob so that it can be used in C literals.
|
||||||
|
Copyright (C) 2018-2021 Free Software Foundation, Inc.
|
||||||
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
|
@@ -16,68 +16,9 @@
|
||||||
|
License along with the GNU C Library; if not, see
|
||||||
|
<https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
-#include <support/support.h>
|
||||||
|
-#include <support/xmemstream.h>
|
||||||
|
+#define CHAR unsigned char
|
||||||
|
+#define L_(C) C
|
||||||
|
+#define SUPPORT_QUOTE_BLOB support_quote_blob
|
||||||
|
+#define WIDE 0
|
||||||
|
|
||||||
|
-char *
|
||||||
|
-support_quote_blob (const void *blob, size_t length)
|
||||||
|
-{
|
||||||
|
- struct xmemstream out;
|
||||||
|
- xopen_memstream (&out);
|
||||||
|
-
|
||||||
|
- const unsigned char *p = blob;
|
||||||
|
- for (size_t i = 0; i < length; ++i)
|
||||||
|
- {
|
||||||
|
- unsigned char ch = p[i];
|
||||||
|
-
|
||||||
|
- /* Use C backslash escapes for those control characters for
|
||||||
|
- which they are defined. */
|
||||||
|
- switch (ch)
|
||||||
|
- {
|
||||||
|
- case '\a':
|
||||||
|
- putc_unlocked ('\\', out.out);
|
||||||
|
- putc_unlocked ('a', out.out);
|
||||||
|
- break;
|
||||||
|
- case '\b':
|
||||||
|
- putc_unlocked ('\\', out.out);
|
||||||
|
- putc_unlocked ('b', out.out);
|
||||||
|
- break;
|
||||||
|
- case '\f':
|
||||||
|
- putc_unlocked ('\\', out.out);
|
||||||
|
- putc_unlocked ('f', out.out);
|
||||||
|
- break;
|
||||||
|
- case '\n':
|
||||||
|
- putc_unlocked ('\\', out.out);
|
||||||
|
- putc_unlocked ('n', out.out);
|
||||||
|
- break;
|
||||||
|
- case '\r':
|
||||||
|
- putc_unlocked ('\\', out.out);
|
||||||
|
- putc_unlocked ('r', out.out);
|
||||||
|
- break;
|
||||||
|
- case '\t':
|
||||||
|
- putc_unlocked ('\\', out.out);
|
||||||
|
- putc_unlocked ('t', out.out);
|
||||||
|
- break;
|
||||||
|
- case '\v':
|
||||||
|
- putc_unlocked ('\\', out.out);
|
||||||
|
- putc_unlocked ('v', out.out);
|
||||||
|
- break;
|
||||||
|
- case '\\':
|
||||||
|
- case '\'':
|
||||||
|
- case '\"':
|
||||||
|
- putc_unlocked ('\\', out.out);
|
||||||
|
- putc_unlocked (ch, out.out);
|
||||||
|
- break;
|
||||||
|
- default:
|
||||||
|
- if (ch < ' ' || ch > '~')
|
||||||
|
- /* Use octal sequences because they are fixed width,
|
||||||
|
- unlike hexadecimal sequences. */
|
||||||
|
- fprintf (out.out, "\\%03o", ch);
|
||||||
|
- else
|
||||||
|
- putc_unlocked (ch, out.out);
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- xfclose_memstream (&out);
|
||||||
|
- return out.buffer;
|
||||||
|
-}
|
||||||
|
+#include "support_quote_blob_main.c"
|
||||||
|
diff --git a/support/support_quote_blob_main.c b/support/support_quote_blob_main.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..19ccfad59311bfee
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/support/support_quote_blob_main.c
|
||||||
|
@@ -0,0 +1,88 @@
|
||||||
|
+/* Quote a blob so that it can be used in C literals.
|
||||||
|
+ Copyright (C) 2018-2021 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <https://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <support/support.h>
|
||||||
|
+#include <support/xmemstream.h>
|
||||||
|
+
|
||||||
|
+char *
|
||||||
|
+SUPPORT_QUOTE_BLOB (const void *blob, size_t length)
|
||||||
|
+{
|
||||||
|
+ struct xmemstream out;
|
||||||
|
+ xopen_memstream (&out);
|
||||||
|
+
|
||||||
|
+ const CHAR *p = blob;
|
||||||
|
+ for (size_t i = 0; i < length; ++i)
|
||||||
|
+ {
|
||||||
|
+ CHAR ch = p[i];
|
||||||
|
+
|
||||||
|
+ /* Use C backslash escapes for those control characters for
|
||||||
|
+ which they are defined. */
|
||||||
|
+ switch (ch)
|
||||||
|
+ {
|
||||||
|
+ case L_('\a'):
|
||||||
|
+ putc_unlocked ('\\', out.out);
|
||||||
|
+ putc_unlocked ('a', out.out);
|
||||||
|
+ break;
|
||||||
|
+ case L_('\b'):
|
||||||
|
+ putc_unlocked ('\\', out.out);
|
||||||
|
+ putc_unlocked ('b', out.out);
|
||||||
|
+ break;
|
||||||
|
+ case L_('\f'):
|
||||||
|
+ putc_unlocked ('\\', out.out);
|
||||||
|
+ putc_unlocked ('f', out.out);
|
||||||
|
+ break;
|
||||||
|
+ case L_('\n'):
|
||||||
|
+ putc_unlocked ('\\', out.out);
|
||||||
|
+ putc_unlocked ('n', out.out);
|
||||||
|
+ break;
|
||||||
|
+ case L_('\r'):
|
||||||
|
+ putc_unlocked ('\\', out.out);
|
||||||
|
+ putc_unlocked ('r', out.out);
|
||||||
|
+ break;
|
||||||
|
+ case L_('\t'):
|
||||||
|
+ putc_unlocked ('\\', out.out);
|
||||||
|
+ putc_unlocked ('t', out.out);
|
||||||
|
+ break;
|
||||||
|
+ case L_('\v'):
|
||||||
|
+ putc_unlocked ('\\', out.out);
|
||||||
|
+ putc_unlocked ('v', out.out);
|
||||||
|
+ break;
|
||||||
|
+ case L_('\\'):
|
||||||
|
+ case L_('\''):
|
||||||
|
+ case L_('\"'):
|
||||||
|
+ putc_unlocked ('\\', out.out);
|
||||||
|
+ putc_unlocked (ch, out.out);
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ if (ch < L_(' ') || ch > L_('~'))
|
||||||
|
+ /* For narrow characters, use octal sequences because they
|
||||||
|
+ are fixed width, unlike hexadecimal sequences. For
|
||||||
|
+ wide characters, use N2785 delimited escape
|
||||||
|
+ sequences. */
|
||||||
|
+ if (WIDE)
|
||||||
|
+ fprintf (out.out, "\\x{%x}", (unsigned int) ch);
|
||||||
|
+ else
|
||||||
|
+ fprintf (out.out, "\\%03o", (unsigned int) ch);
|
||||||
|
+ else
|
||||||
|
+ putc_unlocked (ch, out.out);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ xfclose_memstream (&out);
|
||||||
|
+ return out.buffer;
|
||||||
|
+}
|
||||||
|
diff --git a/support/support_quote_blob_wide.c b/support/support_quote_blob_wide.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..c451ed889c21c626
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/support/support_quote_blob_wide.c
|
||||||
|
@@ -0,0 +1,24 @@
|
||||||
|
+/* Quote a wide string blob so that it can be used in C literals.
|
||||||
|
+ Copyright (C) 2018-2021 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <https://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#define CHAR wchar_t
|
||||||
|
+#define L_(C) L ## C
|
||||||
|
+#define SUPPORT_QUOTE_BLOB support_quote_blob_wide
|
||||||
|
+#define WIDE 1
|
||||||
|
+
|
||||||
|
+#include "support_quote_blob_main.c"
|
||||||
|
diff --git a/support/support_test_compare_string.c b/support/support_test_compare_string.c
|
||||||
|
index cbeaf7b1eeea8ca8..12bafe43d44ae3d7 100644
|
||||||
|
--- a/support/support_test_compare_string.c
|
||||||
|
+++ b/support/support_test_compare_string.c
|
||||||
|
@@ -16,76 +16,13 @@
|
||||||
|
License along with the GNU C Library; if not, see
|
||||||
|
<https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
-#include <stdio.h>
|
||||||
|
-#include <stdlib.h>
|
||||||
|
-#include <string.h>
|
||||||
|
-#include <support/check.h>
|
||||||
|
-#include <support/support.h>
|
||||||
|
-#include <support/xmemstream.h>
|
||||||
|
-
|
||||||
|
-static void
|
||||||
|
-report_length (const char *what, const char *str, size_t length)
|
||||||
|
-{
|
||||||
|
- if (str == NULL)
|
||||||
|
- printf (" %s string: NULL\n", what);
|
||||||
|
- else
|
||||||
|
- printf (" %s string: %zu bytes\n", what, length);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void
|
||||||
|
-report_string (const char *what, const unsigned char *blob,
|
||||||
|
- size_t length, const char *expr)
|
||||||
|
-{
|
||||||
|
- if (length > 0)
|
||||||
|
- {
|
||||||
|
- printf (" %s (evaluated from %s):\n", what, expr);
|
||||||
|
- char *quoted = support_quote_blob (blob, length);
|
||||||
|
- printf (" \"%s\"\n", quoted);
|
||||||
|
- free (quoted);
|
||||||
|
-
|
||||||
|
- fputs (" ", stdout);
|
||||||
|
- for (size_t i = 0; i < length; ++i)
|
||||||
|
- printf (" %02X", blob[i]);
|
||||||
|
- putc ('\n', stdout);
|
||||||
|
- }
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static size_t
|
||||||
|
-string_length_or_zero (const char *str)
|
||||||
|
-{
|
||||||
|
- if (str == NULL)
|
||||||
|
- return 0;
|
||||||
|
- else
|
||||||
|
- return strlen (str);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void
|
||||||
|
-support_test_compare_string (const char *left, const char *right,
|
||||||
|
- const char *file, int line,
|
||||||
|
- const char *left_expr, const char *right_expr)
|
||||||
|
-{
|
||||||
|
- /* Two null pointers are accepted. */
|
||||||
|
- if (left == NULL && right == NULL)
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
- size_t left_length = string_length_or_zero (left);
|
||||||
|
- size_t right_length = string_length_or_zero (right);
|
||||||
|
-
|
||||||
|
- if (left_length != right_length || left == NULL || right == NULL
|
||||||
|
- || memcmp (left, right, left_length) != 0)
|
||||||
|
- {
|
||||||
|
- support_record_failure ();
|
||||||
|
- printf ("%s:%d: error: string comparison failed\n", file, line);
|
||||||
|
- if (left_length == right_length && right != NULL && left != NULL)
|
||||||
|
- printf (" string length: %zu bytes\n", left_length);
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- report_length ("left", left, left_length);
|
||||||
|
- report_length ("right", right, right_length);
|
||||||
|
- }
|
||||||
|
- report_string ("left", (const unsigned char *) left,
|
||||||
|
- left_length, left_expr);
|
||||||
|
- report_string ("right", (const unsigned char *) right,
|
||||||
|
- right_length, right_expr);
|
||||||
|
- }
|
||||||
|
-}
|
||||||
|
+#define CHAR char
|
||||||
|
+#define UCHAR unsigned char
|
||||||
|
+#define LPREFIX ""
|
||||||
|
+#define STRLEN strlen
|
||||||
|
+#define MEMCMP memcmp
|
||||||
|
+#define SUPPORT_QUOTE_BLOB support_quote_blob
|
||||||
|
+#define SUPPORT_TEST_COMPARE_STRING support_test_compare_string
|
||||||
|
+#define WIDE 0
|
||||||
|
+
|
||||||
|
+#include "support_test_compare_string_main.c"
|
||||||
|
diff --git a/support/support_test_compare_string_main.c b/support/support_test_compare_string_main.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..0edc0ca97d79d71e
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/support/support_test_compare_string_main.c
|
||||||
|
@@ -0,0 +1,94 @@
|
||||||
|
+/* Check two strings for equality.
|
||||||
|
+ Copyright (C) 2018-2021 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <https://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <wchar.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/support.h>
|
||||||
|
+#include <support/xmemstream.h>
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+report_length (const char *what, const CHAR *str, size_t length)
|
||||||
|
+{
|
||||||
|
+ if (str == NULL)
|
||||||
|
+ printf (" %s string: NULL\n", what);
|
||||||
|
+ else
|
||||||
|
+ printf (" %s string: %zu %s\n", what, length,
|
||||||
|
+ WIDE ? "wide characters" : "bytes");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+report_string (const char *what, const UCHAR *blob,
|
||||||
|
+ size_t length, const char *expr)
|
||||||
|
+{
|
||||||
|
+ if (length > 0)
|
||||||
|
+ {
|
||||||
|
+ printf (" %s (evaluated from %s):\n", what, expr);
|
||||||
|
+ char *quoted = SUPPORT_QUOTE_BLOB (blob, length);
|
||||||
|
+ printf (" %s\"%s\"\n", LPREFIX, quoted);
|
||||||
|
+ free (quoted);
|
||||||
|
+
|
||||||
|
+ fputs (" ", stdout);
|
||||||
|
+ for (size_t i = 0; i < length; ++i)
|
||||||
|
+ printf (" %02X", (unsigned int) blob[i]);
|
||||||
|
+ putc ('\n', stdout);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static size_t
|
||||||
|
+string_length_or_zero (const CHAR *str)
|
||||||
|
+{
|
||||||
|
+ if (str == NULL)
|
||||||
|
+ return 0;
|
||||||
|
+ else
|
||||||
|
+ return STRLEN (str);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+SUPPORT_TEST_COMPARE_STRING (const CHAR *left, const CHAR *right,
|
||||||
|
+ const char *file, int line,
|
||||||
|
+ const char *left_expr, const char *right_expr)
|
||||||
|
+{
|
||||||
|
+ /* Two null pointers are accepted. */
|
||||||
|
+ if (left == NULL && right == NULL)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ size_t left_length = string_length_or_zero (left);
|
||||||
|
+ size_t right_length = string_length_or_zero (right);
|
||||||
|
+
|
||||||
|
+ if (left_length != right_length || left == NULL || right == NULL
|
||||||
|
+ || MEMCMP (left, right, left_length) != 0)
|
||||||
|
+ {
|
||||||
|
+ support_record_failure ();
|
||||||
|
+ printf ("%s:%d: error: string comparison failed\n", file, line);
|
||||||
|
+ if (left_length == right_length && right != NULL && left != NULL)
|
||||||
|
+ printf (" string length: %zu %s\n", left_length,
|
||||||
|
+ WIDE ? "wide characters" : "bytes");
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ report_length ("left", left, left_length);
|
||||||
|
+ report_length ("right", right, right_length);
|
||||||
|
+ }
|
||||||
|
+ report_string ("left", (const UCHAR *) left,
|
||||||
|
+ left_length, left_expr);
|
||||||
|
+ report_string ("right", (const UCHAR *) right,
|
||||||
|
+ right_length, right_expr);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
diff --git a/support/support_test_compare_string_wide.c b/support/support_test_compare_string_wide.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..88b560b142a3c356
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/support/support_test_compare_string_wide.c
|
||||||
|
@@ -0,0 +1,28 @@
|
||||||
|
+/* Check two wide strings for equality.
|
||||||
|
+ Copyright (C) 2018-2021 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <https://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#define CHAR wchar_t
|
||||||
|
+#define UCHAR wchar_t
|
||||||
|
+#define LPREFIX "L"
|
||||||
|
+#define STRLEN wcslen
|
||||||
|
+#define MEMCMP wmemcmp
|
||||||
|
+#define SUPPORT_QUOTE_BLOB support_quote_blob_wide
|
||||||
|
+#define SUPPORT_TEST_COMPARE_STRING support_test_compare_string_wide
|
||||||
|
+#define WIDE 1
|
||||||
|
+
|
||||||
|
+#include "support_test_compare_string_main.c"
|
||||||
|
diff --git a/support/tst-support_quote_blob_wide.c b/support/tst-support_quote_blob_wide.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..ea71a1f7f873b23a
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/support/tst-support_quote_blob_wide.c
|
||||||
|
@@ -0,0 +1,66 @@
|
||||||
|
+/* Test the support_quote_blob_wide function.
|
||||||
|
+ Copyright (C) 2018-2021 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <https://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/support.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ /* Check handling of the empty blob, both with and without trailing
|
||||||
|
+ NUL byte. */
|
||||||
|
+ char *p = support_quote_blob_wide (L"", 0);
|
||||||
|
+ TEST_COMPARE (strlen (p), 0);
|
||||||
|
+ free (p);
|
||||||
|
+ p = support_quote_blob_wide (L"X", 0);
|
||||||
|
+ TEST_COMPARE (strlen (p), 0);
|
||||||
|
+ free (p);
|
||||||
|
+
|
||||||
|
+ /* Check escaping of backslash-escaped characters, and lack of
|
||||||
|
+ escaping for other shell meta-characters. */
|
||||||
|
+ p = support_quote_blob_wide (L"$()*?`@[]{}~\'\"X", 14);
|
||||||
|
+ TEST_COMPARE (strcmp (p, "$()*?`@[]{}~\\'\\\""), 0);
|
||||||
|
+ free (p);
|
||||||
|
+
|
||||||
|
+ /* Check lack of escaping for letters and digits. */
|
||||||
|
+#define LETTERS_AND_DIGTS \
|
||||||
|
+ "abcdefghijklmnopqrstuvwxyz" \
|
||||||
|
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
|
||||||
|
+ "0123456789"
|
||||||
|
+#define CONCATX(X, Y) X ## Y
|
||||||
|
+#define CONCAT(X, Y) CONCATX (X, Y)
|
||||||
|
+#define WLETTERS_AND_DIGTS CONCAT (L, LETTERS_AND_DIGTS)
|
||||||
|
+ p = support_quote_blob_wide (WLETTERS_AND_DIGTS "@", 2 * 26 + 10);
|
||||||
|
+ TEST_COMPARE (strcmp (p, LETTERS_AND_DIGTS), 0);
|
||||||
|
+ free (p);
|
||||||
|
+
|
||||||
|
+ /* Check escaping of control characters and other non-printable
|
||||||
|
+ characters. */
|
||||||
|
+ p = support_quote_blob_wide (L"\r\n\t\a\b\f\v\1\177\200\377"
|
||||||
|
+ "\x123\x76543210\xfedcba98\0@", 17);
|
||||||
|
+ TEST_COMPARE (strcmp (p, "\\r\\n\\t\\a\\b\\f\\v\\x{1}"
|
||||||
|
+ "\\x{7f}\\x{80}\\x{ff}\\x{123}\\x{76543210}"
|
||||||
|
+ "\\x{fedcba98}\\x{0}@\\x{0}"), 0);
|
||||||
|
+ free (p);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff --git a/support/tst-test_compare_string_wide.c b/support/tst-test_compare_string_wide.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..548f7dcdc60b82d8
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/support/tst-test_compare_string_wide.c
|
||||||
|
@@ -0,0 +1,107 @@
|
||||||
|
+/* Basic test for the TEST_COMPARE_STRING_WIDE macro.
|
||||||
|
+ Copyright (C) 2018-2021 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <https://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/capture_subprocess.h>
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+subprocess (void *closure)
|
||||||
|
+{
|
||||||
|
+ /* These tests should fail. They were chosen to cover differences
|
||||||
|
+ in length (with the same contents), single-bit mismatches, and
|
||||||
|
+ mismatching null pointers. */
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (L"", NULL); /* Line 29. */
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (L"X", L""); /* Line 30. */
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (NULL, L"X"); /* Line 31. */
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (L"abcd", L"abcD"); /* Line 32. */
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (L"abcd", NULL); /* Line 33. */
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (NULL, L"abcd"); /* Line 34. */
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Same contents, different addresses. */
|
||||||
|
+wchar_t buffer_abc_1[] = L"abc";
|
||||||
|
+wchar_t buffer_abc_2[] = L"abc";
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ /* This should succeed. Even if the pointers and array contents are
|
||||||
|
+ different, zero-length inputs are not different. */
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (NULL, NULL);
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (L"", L"");
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (buffer_abc_1, buffer_abc_2);
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (buffer_abc_1, L"abc");
|
||||||
|
+
|
||||||
|
+ struct support_capture_subprocess proc = support_capture_subprocess
|
||||||
|
+ (&subprocess, NULL);
|
||||||
|
+
|
||||||
|
+ /* Discard the reported error. */
|
||||||
|
+ support_record_failure_reset ();
|
||||||
|
+
|
||||||
|
+ puts ("info: *** subprocess output starts ***");
|
||||||
|
+ fputs (proc.out.buffer, stdout);
|
||||||
|
+ puts ("info: *** subprocess output ends ***");
|
||||||
|
+
|
||||||
|
+ TEST_VERIFY
|
||||||
|
+ (strcmp (proc.out.buffer,
|
||||||
|
+"tst-test_compare_string_wide.c:29: error: string comparison failed\n"
|
||||||
|
+" left string: 0 wide characters\n"
|
||||||
|
+" right string: NULL\n"
|
||||||
|
+"tst-test_compare_string_wide.c:30: error: string comparison failed\n"
|
||||||
|
+" left string: 1 wide characters\n"
|
||||||
|
+" right string: 0 wide characters\n"
|
||||||
|
+" left (evaluated from L\"X\"):\n"
|
||||||
|
+" L\"X\"\n"
|
||||||
|
+" 58\n"
|
||||||
|
+"tst-test_compare_string_wide.c:31: error: string comparison failed\n"
|
||||||
|
+" left string: NULL\n"
|
||||||
|
+" right string: 1 wide characters\n"
|
||||||
|
+" right (evaluated from L\"X\"):\n"
|
||||||
|
+" L\"X\"\n"
|
||||||
|
+" 58\n"
|
||||||
|
+"tst-test_compare_string_wide.c:32: error: string comparison failed\n"
|
||||||
|
+" string length: 4 wide characters\n"
|
||||||
|
+" left (evaluated from L\"abcd\"):\n"
|
||||||
|
+" L\"abcd\"\n"
|
||||||
|
+" 61 62 63 64\n"
|
||||||
|
+" right (evaluated from L\"abcD\"):\n"
|
||||||
|
+" L\"abcD\"\n"
|
||||||
|
+" 61 62 63 44\n"
|
||||||
|
+"tst-test_compare_string_wide.c:33: error: string comparison failed\n"
|
||||||
|
+" left string: 4 wide characters\n"
|
||||||
|
+" right string: NULL\n"
|
||||||
|
+" left (evaluated from L\"abcd\"):\n"
|
||||||
|
+" L\"abcd\"\n"
|
||||||
|
+" 61 62 63 64\n"
|
||||||
|
+"tst-test_compare_string_wide.c:34: error: string comparison failed\n"
|
||||||
|
+" left string: NULL\n"
|
||||||
|
+" right string: 4 wide characters\n"
|
||||||
|
+" right (evaluated from L\"abcd\"):\n"
|
||||||
|
+" L\"abcd\"\n"
|
||||||
|
+" 61 62 63 64\n"
|
||||||
|
+ ) == 0);
|
||||||
|
+
|
||||||
|
+ /* Check that there is no output on standard error. */
|
||||||
|
+ support_capture_subprocess_check (&proc, "TEST_COMPARE_STRING_WIDE",
|
||||||
|
+ 0, sc_allow_stdout);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
691
SOURCES/glibc-c-utf8-locale-5.patch
Normal file
691
SOURCES/glibc-c-utf8-locale-5.patch
Normal file
@ -0,0 +1,691 @@
|
|||||||
|
commit 7e0ad15c0fbfe25435c1acd0ed3e9cedfbff2488
|
||||||
|
Author: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
Date: Mon Jan 31 00:34:42 2022 -0500
|
||||||
|
|
||||||
|
localedata: Adjust C.UTF-8 to align with C/POSIX.
|
||||||
|
|
||||||
|
We have had one downstream report from Canonical [1] that
|
||||||
|
an rrdtool test was broken by the differences in LC_TIME
|
||||||
|
that we had in the non-builtin C locale (C.UTF-8). If one
|
||||||
|
application has an issue there are going to be others, and
|
||||||
|
so with this commit we review and fix all the issues that
|
||||||
|
cause the builtin C locale to be different from C.UTF-8,
|
||||||
|
which includes:
|
||||||
|
* mon_decimal_point should be empty e.g. ""
|
||||||
|
- Depends on mon_decimal_point_wc fix.
|
||||||
|
* negative_sign should be empty e.g. ""
|
||||||
|
* week should be aligned with the builtin C/POSIX locale
|
||||||
|
* d_fmt corrected with escaped slashes e.g. "%m//%d//%y"
|
||||||
|
* yesstr and nostr should be empty e.g. ""
|
||||||
|
* country_ab2 and country_ab3 should be empty e.g. ""
|
||||||
|
|
||||||
|
We bump LC_IDENTIFICATION version and adjust the date to
|
||||||
|
indicate the change in the locale.
|
||||||
|
|
||||||
|
A new tst-c-utf8-consistency test is added to ensure
|
||||||
|
consistency between C/POSIX and C.UTF-8.
|
||||||
|
|
||||||
|
Tested on x86_64 and i686 without regression.
|
||||||
|
|
||||||
|
[1] https://sourceware.org/pipermail/libc-alpha/2022-January/135703.html
|
||||||
|
|
||||||
|
Co-authored-by: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Reviewed-by: Florian Weimer <fweimer@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/localedata/Makefile b/localedata/Makefile
|
||||||
|
index c9dd5a954e8194cc..5830b9d05141cccd 100644
|
||||||
|
--- a/localedata/Makefile
|
||||||
|
+++ b/localedata/Makefile
|
||||||
|
@@ -155,11 +155,31 @@ locale_test_suite := tst_iswalnum tst_iswalpha tst_iswcntrl \
|
||||||
|
tst_wcsxfrm tst_wctob tst_wctomb tst_wctrans \
|
||||||
|
tst_wctype tst_wcwidth
|
||||||
|
|
||||||
|
-tests = $(locale_test_suite) tst-digits tst-setlocale bug-iconv-trans \
|
||||||
|
- tst-leaks tst-mbswcs1 tst-mbswcs2 tst-mbswcs3 tst-mbswcs4 tst-mbswcs5 \
|
||||||
|
- tst-mbswcs6 tst-xlocale1 tst-xlocale2 bug-usesetlocale \
|
||||||
|
- tst-strfmon1 tst-sscanf bug-setlocale1 tst-setlocale2 tst-setlocale3 \
|
||||||
|
- tst-wctype tst-iconv-math-trans
|
||||||
|
+tests = \
|
||||||
|
+ $(locale_test_suite) \
|
||||||
|
+ bug-iconv-trans \
|
||||||
|
+ bug-setlocale1 \
|
||||||
|
+ bug-usesetlocale \
|
||||||
|
+ tst-c-utf8-consistency \
|
||||||
|
+ tst-digits \
|
||||||
|
+ tst-iconv-math-trans \
|
||||||
|
+ tst-leaks \
|
||||||
|
+ tst-mbswcs1 \
|
||||||
|
+ tst-mbswcs2 \
|
||||||
|
+ tst-mbswcs3 \
|
||||||
|
+ tst-mbswcs4 \
|
||||||
|
+ tst-mbswcs5 \
|
||||||
|
+ tst-mbswcs6 \
|
||||||
|
+ tst-setlocale \
|
||||||
|
+ tst-setlocale2 \
|
||||||
|
+ tst-setlocale3 \
|
||||||
|
+ tst-sscanf \
|
||||||
|
+ tst-strfmon1 \
|
||||||
|
+ tst-wctype \
|
||||||
|
+ tst-xlocale1 \
|
||||||
|
+ tst-xlocale2 \
|
||||||
|
+ # tests
|
||||||
|
+
|
||||||
|
tests-static = bug-setlocale1-static
|
||||||
|
tests += $(tests-static)
|
||||||
|
ifeq (yes,$(build-shared))
|
||||||
|
diff --git a/localedata/locales/C b/localedata/locales/C
|
||||||
|
index ca801c79cf7e953e..fc0614e551519c6b 100644
|
||||||
|
--- a/localedata/locales/C
|
||||||
|
+++ b/localedata/locales/C
|
||||||
|
@@ -12,8 +12,8 @@ tel ""
|
||||||
|
fax ""
|
||||||
|
language ""
|
||||||
|
territory ""
|
||||||
|
-revision "2.0"
|
||||||
|
-date "2020-06-28"
|
||||||
|
+revision "2.1"
|
||||||
|
+date "2022-01-30"
|
||||||
|
category "i18n:2012";LC_IDENTIFICATION
|
||||||
|
category "i18n:2012";LC_CTYPE
|
||||||
|
category "i18n:2012";LC_COLLATE
|
||||||
|
@@ -68,11 +68,11 @@ LC_MONETARY
|
||||||
|
% glibc/locale/C-monetary.c.).
|
||||||
|
int_curr_symbol ""
|
||||||
|
currency_symbol ""
|
||||||
|
-mon_decimal_point "."
|
||||||
|
+mon_decimal_point ""
|
||||||
|
mon_thousands_sep ""
|
||||||
|
mon_grouping -1
|
||||||
|
positive_sign ""
|
||||||
|
-negative_sign "-"
|
||||||
|
+negative_sign ""
|
||||||
|
int_frac_digits -1
|
||||||
|
frac_digits -1
|
||||||
|
p_cs_precedes -1
|
||||||
|
@@ -121,7 +121,9 @@ mon "January";"February";"March";"April";"May";"June";"July";/
|
||||||
|
%
|
||||||
|
% ISO 8601 conforming applications should use the values 7, 19971201 (a
|
||||||
|
% Monday), and 4 (Thursday), respectively.
|
||||||
|
-week 7;19971201;4
|
||||||
|
+%
|
||||||
|
+% This field is consciously aligned with the builtin C/POSIX locale.
|
||||||
|
+week 7;19971130;4
|
||||||
|
first_weekday 1
|
||||||
|
first_workday 2
|
||||||
|
|
||||||
|
@@ -129,7 +131,7 @@ first_workday 2
|
||||||
|
d_t_fmt "%a %b %e %H:%M:%S %Y"
|
||||||
|
|
||||||
|
% Appropriate date representation (%x)
|
||||||
|
-d_fmt "%m/%d/%y"
|
||||||
|
+d_fmt "%m//%d//%y"
|
||||||
|
|
||||||
|
% Appropriate time representation (%X)
|
||||||
|
t_fmt "%H:%M:%S"
|
||||||
|
@@ -150,8 +152,8 @@ LC_MESSAGES
|
||||||
|
%
|
||||||
|
yesexpr "^[yY]"
|
||||||
|
noexpr "^[nN]"
|
||||||
|
-yesstr "Yes"
|
||||||
|
-nostr "No"
|
||||||
|
+yesstr ""
|
||||||
|
+nostr ""
|
||||||
|
END LC_MESSAGES
|
||||||
|
|
||||||
|
LC_PAPER
|
||||||
|
@@ -175,6 +177,10 @@ LC_ADDRESS
|
||||||
|
% the LC_ADDRESS category.
|
||||||
|
% (also used in the built in C/POSIX locale in glibc/locale/C-address.c)
|
||||||
|
postal_fmt "%a%N%f%N%d%N%b%N%s %h %e %r%N%C-%z %T%N%c%N"
|
||||||
|
+% The abbreviated 2 char and 3 char should be set to empty strings to
|
||||||
|
+% match the C/POSIX locale.
|
||||||
|
+country_ab2 ""
|
||||||
|
+country_ab3 ""
|
||||||
|
END LC_ADDRESS
|
||||||
|
|
||||||
|
LC_TELEPHONE
|
||||||
|
diff --git a/localedata/tst-c-utf8-consistency.c b/localedata/tst-c-utf8-consistency.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..50feed3090df0ff1
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/localedata/tst-c-utf8-consistency.c
|
||||||
|
@@ -0,0 +1,539 @@
|
||||||
|
+/* Test that C/POSIX and C.UTF-8 are consistent.
|
||||||
|
+ Copyright (C) 2022 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ License as published by the Free Software Foundation; either
|
||||||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ Lesser General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ License along with the GNU C Library; if not, see
|
||||||
|
+ <https://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <langinfo.h>
|
||||||
|
+#include <locale.h>
|
||||||
|
+#include <stdbool.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+
|
||||||
|
+/* Initialized by do_test using newlocale. */
|
||||||
|
+static locale_t c_utf8;
|
||||||
|
+
|
||||||
|
+/* Set to true for second pass. */
|
||||||
|
+static bool use_nl_langinfo_l;
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+switch_to_c (void)
|
||||||
|
+{
|
||||||
|
+ if (setlocale (LC_ALL, "C") == NULL)
|
||||||
|
+ FAIL_EXIT1 ("setlocale (LC_ALL, \"C\")");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+switch_to_c_utf8 (void)
|
||||||
|
+{
|
||||||
|
+ if (setlocale (LC_ALL, "C.UTF-8") == NULL)
|
||||||
|
+ FAIL_EXIT1 ("setlocale (LC_ALL, \"C.UTF-8\")");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static char *
|
||||||
|
+str (nl_item item)
|
||||||
|
+{
|
||||||
|
+ if (!use_nl_langinfo_l)
|
||||||
|
+ switch_to_c ();
|
||||||
|
+ return nl_langinfo (item);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static char *
|
||||||
|
+str_utf8 (nl_item item)
|
||||||
|
+{
|
||||||
|
+ if (use_nl_langinfo_l)
|
||||||
|
+ return nl_langinfo_l (item, c_utf8);
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ switch_to_c_utf8 ();
|
||||||
|
+ return nl_langinfo (item);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static wchar_t *
|
||||||
|
+wstr (nl_item item)
|
||||||
|
+{
|
||||||
|
+ return (wchar_t *) str (item);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static wchar_t *
|
||||||
|
+wstr_utf8 (nl_item item)
|
||||||
|
+{
|
||||||
|
+ return (wchar_t *) str_utf8 (item);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+byte (nl_item item)
|
||||||
|
+{
|
||||||
|
+ return (signed char) *str (item);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+byte_utf8 (nl_item item)
|
||||||
|
+{
|
||||||
|
+ return (signed char) *str_utf8 (item);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+word (nl_item item)
|
||||||
|
+{
|
||||||
|
+ union
|
||||||
|
+ {
|
||||||
|
+ char *ptr;
|
||||||
|
+ int word;
|
||||||
|
+ } u;
|
||||||
|
+ u.ptr = str (item);
|
||||||
|
+ return u.word;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+word_utf8 (nl_item item)
|
||||||
|
+{
|
||||||
|
+ union
|
||||||
|
+ {
|
||||||
|
+ char *ptr;
|
||||||
|
+ int word;
|
||||||
|
+ } u;
|
||||||
|
+ u.ptr = str_utf8 (item);
|
||||||
|
+ return u.word;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+one_pass (void)
|
||||||
|
+{
|
||||||
|
+ /* LC_TIME. */
|
||||||
|
+ TEST_COMPARE_STRING (str (ABDAY_1), str_utf8 (ABDAY_1));
|
||||||
|
+ TEST_COMPARE_STRING (str (ABDAY_2), str_utf8 (ABDAY_2));
|
||||||
|
+ TEST_COMPARE_STRING (str (ABDAY_3), str_utf8 (ABDAY_3));
|
||||||
|
+ TEST_COMPARE_STRING (str (ABDAY_4), str_utf8 (ABDAY_4));
|
||||||
|
+ TEST_COMPARE_STRING (str (ABDAY_5), str_utf8 (ABDAY_5));
|
||||||
|
+ TEST_COMPARE_STRING (str (ABDAY_6), str_utf8 (ABDAY_6));
|
||||||
|
+ TEST_COMPARE_STRING (str (ABDAY_7), str_utf8 (ABDAY_7));
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE_STRING (str (DAY_1), str_utf8 (DAY_1));
|
||||||
|
+ TEST_COMPARE_STRING (str (DAY_2), str_utf8 (DAY_2));
|
||||||
|
+ TEST_COMPARE_STRING (str (DAY_3), str_utf8 (DAY_3));
|
||||||
|
+ TEST_COMPARE_STRING (str (DAY_4), str_utf8 (DAY_4));
|
||||||
|
+ TEST_COMPARE_STRING (str (DAY_5), str_utf8 (DAY_5));
|
||||||
|
+ TEST_COMPARE_STRING (str (DAY_6), str_utf8 (DAY_6));
|
||||||
|
+ TEST_COMPARE_STRING (str (DAY_7), str_utf8 (DAY_7));
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE_STRING (str (ABMON_1), str_utf8 (ABMON_1));
|
||||||
|
+ TEST_COMPARE_STRING (str (ABMON_2), str_utf8 (ABMON_2));
|
||||||
|
+ TEST_COMPARE_STRING (str (ABMON_3), str_utf8 (ABMON_3));
|
||||||
|
+ TEST_COMPARE_STRING (str (ABMON_4), str_utf8 (ABMON_4));
|
||||||
|
+ TEST_COMPARE_STRING (str (ABMON_5), str_utf8 (ABMON_5));
|
||||||
|
+ TEST_COMPARE_STRING (str (ABMON_6), str_utf8 (ABMON_6));
|
||||||
|
+ TEST_COMPARE_STRING (str (ABMON_7), str_utf8 (ABMON_7));
|
||||||
|
+ TEST_COMPARE_STRING (str (ABMON_8), str_utf8 (ABMON_8));
|
||||||
|
+ TEST_COMPARE_STRING (str (ABMON_9), str_utf8 (ABMON_9));
|
||||||
|
+ TEST_COMPARE_STRING (str (ABMON_10), str_utf8 (ABMON_10));
|
||||||
|
+ TEST_COMPARE_STRING (str (ABMON_11), str_utf8 (ABMON_11));
|
||||||
|
+ TEST_COMPARE_STRING (str (ABMON_12), str_utf8 (ABMON_12));
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE_STRING (str (MON_1), str_utf8 (MON_1));
|
||||||
|
+ TEST_COMPARE_STRING (str (MON_2), str_utf8 (MON_2));
|
||||||
|
+ TEST_COMPARE_STRING (str (MON_3), str_utf8 (MON_3));
|
||||||
|
+ TEST_COMPARE_STRING (str (MON_4), str_utf8 (MON_4));
|
||||||
|
+ TEST_COMPARE_STRING (str (MON_5), str_utf8 (MON_5));
|
||||||
|
+ TEST_COMPARE_STRING (str (MON_6), str_utf8 (MON_6));
|
||||||
|
+ TEST_COMPARE_STRING (str (MON_7), str_utf8 (MON_7));
|
||||||
|
+ TEST_COMPARE_STRING (str (MON_8), str_utf8 (MON_8));
|
||||||
|
+ TEST_COMPARE_STRING (str (MON_9), str_utf8 (MON_9));
|
||||||
|
+ TEST_COMPARE_STRING (str (MON_10), str_utf8 (MON_10));
|
||||||
|
+ TEST_COMPARE_STRING (str (MON_11), str_utf8 (MON_11));
|
||||||
|
+ TEST_COMPARE_STRING (str (MON_12), str_utf8 (MON_12));
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE_STRING (str (AM_STR), str_utf8 (AM_STR));
|
||||||
|
+ TEST_COMPARE_STRING (str (PM_STR), str_utf8 (PM_STR));
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE_STRING (str (D_T_FMT), str_utf8 (D_T_FMT));
|
||||||
|
+ TEST_COMPARE_STRING (str (D_FMT), str_utf8 (D_FMT));
|
||||||
|
+ TEST_COMPARE_STRING (str (T_FMT), str_utf8 (T_FMT));
|
||||||
|
+ TEST_COMPARE_STRING (str (T_FMT_AMPM),
|
||||||
|
+ str_utf8 (T_FMT_AMPM));
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE_STRING (str (ERA), str_utf8 (ERA));
|
||||||
|
+ TEST_COMPARE_STRING (str (ERA_YEAR), str_utf8 (ERA_YEAR));
|
||||||
|
+ TEST_COMPARE_STRING (str (ERA_D_FMT), str_utf8 (ERA_D_FMT));
|
||||||
|
+ TEST_COMPARE_STRING (str (ALT_DIGITS), str_utf8 (ALT_DIGITS));
|
||||||
|
+ TEST_COMPARE_STRING (str (ERA_D_T_FMT), str_utf8 (ERA_D_T_FMT));
|
||||||
|
+ TEST_COMPARE_STRING (str (ERA_T_FMT), str_utf8 (ERA_T_FMT));
|
||||||
|
+ TEST_COMPARE (word (_NL_TIME_ERA_NUM_ENTRIES),
|
||||||
|
+ word_utf8 (_NL_TIME_ERA_NUM_ENTRIES));
|
||||||
|
+ /* No array elements, so nothing to compare for _NL_TIME_ERA_ENTRIES. */
|
||||||
|
+ TEST_COMPARE (word (_NL_TIME_ERA_NUM_ENTRIES), 0);
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABDAY_1), wstr_utf8 (_NL_WABDAY_1));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABDAY_2), wstr_utf8 (_NL_WABDAY_2));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABDAY_3), wstr_utf8 (_NL_WABDAY_3));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABDAY_4), wstr_utf8 (_NL_WABDAY_4));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABDAY_5), wstr_utf8 (_NL_WABDAY_5));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABDAY_6), wstr_utf8 (_NL_WABDAY_6));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABDAY_7), wstr_utf8 (_NL_WABDAY_7));
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WDAY_1), wstr_utf8 (_NL_WDAY_1));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WDAY_2), wstr_utf8 (_NL_WDAY_2));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WDAY_3), wstr_utf8 (_NL_WDAY_3));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WDAY_4), wstr_utf8 (_NL_WDAY_4));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WDAY_5), wstr_utf8 (_NL_WDAY_5));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WDAY_6), wstr_utf8 (_NL_WDAY_6));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WDAY_7), wstr_utf8 (_NL_WDAY_7));
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_1), wstr_utf8 (_NL_WABMON_1));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_2), wstr_utf8 (_NL_WABMON_2));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_3), wstr_utf8 (_NL_WABMON_3));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_4), wstr_utf8 (_NL_WABMON_4));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_5), wstr_utf8 (_NL_WABMON_5));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_6), wstr_utf8 (_NL_WABMON_6));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_7), wstr_utf8 (_NL_WABMON_7));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_8), wstr_utf8 (_NL_WABMON_8));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_9), wstr_utf8 (_NL_WABMON_9));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_10), wstr_utf8 (_NL_WABMON_10));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_11), wstr_utf8 (_NL_WABMON_11));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_12), wstr_utf8 (_NL_WABMON_12));
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_1), wstr_utf8 (_NL_WMON_1));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_2), wstr_utf8 (_NL_WMON_2));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_3), wstr_utf8 (_NL_WMON_3));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_4), wstr_utf8 (_NL_WMON_4));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_5), wstr_utf8 (_NL_WMON_5));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_6), wstr_utf8 (_NL_WMON_6));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_7), wstr_utf8 (_NL_WMON_7));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_8), wstr_utf8 (_NL_WMON_8));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_9), wstr_utf8 (_NL_WMON_9));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_10), wstr_utf8 (_NL_WMON_10));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_11), wstr_utf8 (_NL_WMON_11));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_12), wstr_utf8 (_NL_WMON_12));
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WAM_STR), wstr_utf8 (_NL_WAM_STR));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WPM_STR), wstr_utf8 (_NL_WPM_STR));
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WD_T_FMT), wstr_utf8 (_NL_WD_T_FMT));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WD_FMT), wstr_utf8 (_NL_WD_FMT));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WT_FMT), wstr_utf8 (_NL_WT_FMT));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WT_FMT_AMPM),
|
||||||
|
+ wstr_utf8 (_NL_WT_FMT_AMPM));
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WERA_YEAR), wstr_utf8 (_NL_WERA_YEAR));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WERA_D_FMT), wstr_utf8 (_NL_WERA_D_FMT));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALT_DIGITS),
|
||||||
|
+ wstr_utf8 (_NL_WALT_DIGITS));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WERA_D_T_FMT),
|
||||||
|
+ wstr_utf8 (_NL_WERA_D_T_FMT));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WERA_T_FMT), wstr_utf8 (_NL_WERA_T_FMT));
|
||||||
|
+
|
||||||
|
+ /* This is somewhat inconsistent, but see locale/categories.def. */
|
||||||
|
+ TEST_COMPARE (byte (_NL_TIME_WEEK_NDAYS), byte_utf8 (_NL_TIME_WEEK_NDAYS));
|
||||||
|
+ TEST_COMPARE (word (_NL_TIME_WEEK_1STDAY),
|
||||||
|
+ word_utf8 (_NL_TIME_WEEK_1STDAY));
|
||||||
|
+ TEST_COMPARE (byte (_NL_TIME_WEEK_1STWEEK),
|
||||||
|
+ byte_utf8 (_NL_TIME_WEEK_1STWEEK));
|
||||||
|
+ TEST_COMPARE (byte (_NL_TIME_FIRST_WEEKDAY),
|
||||||
|
+ byte_utf8 (_NL_TIME_FIRST_WEEKDAY));
|
||||||
|
+ TEST_COMPARE (byte (_NL_TIME_FIRST_WORKDAY),
|
||||||
|
+ byte_utf8 (_NL_TIME_FIRST_WORKDAY));
|
||||||
|
+ TEST_COMPARE (byte (_NL_TIME_CAL_DIRECTION),
|
||||||
|
+ byte_utf8 (_NL_TIME_CAL_DIRECTION));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_TIME_TIMEZONE), str_utf8 (_NL_TIME_TIMEZONE));
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE_STRING (str (_DATE_FMT), str_utf8 (_DATE_FMT));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_W_DATE_FMT), wstr_utf8 (_NL_W_DATE_FMT));
|
||||||
|
+
|
||||||
|
+ /* Expected difference. */
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_TIME_CODESET), "ANSI_X3.4-1968");
|
||||||
|
+ TEST_COMPARE_STRING (str_utf8 (_NL_TIME_CODESET), "UTF-8");
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE_STRING (str (ALTMON_1), str_utf8 (ALTMON_1));
|
||||||
|
+ TEST_COMPARE_STRING (str (ALTMON_2), str_utf8 (ALTMON_2));
|
||||||
|
+ TEST_COMPARE_STRING (str (ALTMON_3), str_utf8 (ALTMON_3));
|
||||||
|
+ TEST_COMPARE_STRING (str (ALTMON_4), str_utf8 (ALTMON_4));
|
||||||
|
+ TEST_COMPARE_STRING (str (ALTMON_5), str_utf8 (ALTMON_5));
|
||||||
|
+ TEST_COMPARE_STRING (str (ALTMON_6), str_utf8 (ALTMON_6));
|
||||||
|
+ TEST_COMPARE_STRING (str (ALTMON_7), str_utf8 (ALTMON_7));
|
||||||
|
+ TEST_COMPARE_STRING (str (ALTMON_8), str_utf8 (ALTMON_8));
|
||||||
|
+ TEST_COMPARE_STRING (str (ALTMON_9), str_utf8 (ALTMON_9));
|
||||||
|
+ TEST_COMPARE_STRING (str (ALTMON_10), str_utf8 (ALTMON_10));
|
||||||
|
+ TEST_COMPARE_STRING (str (ALTMON_11), str_utf8 (ALTMON_11));
|
||||||
|
+ TEST_COMPARE_STRING (str (ALTMON_12), str_utf8 (ALTMON_12));
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_1), wstr_utf8 (_NL_WALTMON_1));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_2), wstr_utf8 (_NL_WALTMON_2));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_3), wstr_utf8 (_NL_WALTMON_3));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_4), wstr_utf8 (_NL_WALTMON_4));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_5), wstr_utf8 (_NL_WALTMON_5));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_6), wstr_utf8 (_NL_WALTMON_6));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_7), wstr_utf8 (_NL_WALTMON_7));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_8), wstr_utf8 (_NL_WALTMON_8));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_9), wstr_utf8 (_NL_WALTMON_9));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_10), wstr_utf8 (_NL_WALTMON_10));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_11), wstr_utf8 (_NL_WALTMON_11));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_12), wstr_utf8 (_NL_WALTMON_12));
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_1), str_utf8 (_NL_ABALTMON_1));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_2), str_utf8 (_NL_ABALTMON_2));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_3), str_utf8 (_NL_ABALTMON_3));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_4), str_utf8 (_NL_ABALTMON_4));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_5), str_utf8 (_NL_ABALTMON_5));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_6), str_utf8 (_NL_ABALTMON_6));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_7), str_utf8 (_NL_ABALTMON_7));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_8), str_utf8 (_NL_ABALTMON_8));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_9), str_utf8 (_NL_ABALTMON_9));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_10), str_utf8 (_NL_ABALTMON_10));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_11), str_utf8 (_NL_ABALTMON_11));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_12), str_utf8 (_NL_ABALTMON_12));
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_1),
|
||||||
|
+ wstr_utf8 (_NL_WABALTMON_1));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_2),
|
||||||
|
+ wstr_utf8 (_NL_WABALTMON_2));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_3),
|
||||||
|
+ wstr_utf8 (_NL_WABALTMON_3));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_4),
|
||||||
|
+ wstr_utf8 (_NL_WABALTMON_4));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_5),
|
||||||
|
+ wstr_utf8 (_NL_WABALTMON_5));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_6),
|
||||||
|
+ wstr_utf8 (_NL_WABALTMON_6));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_7),
|
||||||
|
+ wstr_utf8 (_NL_WABALTMON_7));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_8),
|
||||||
|
+ wstr_utf8 (_NL_WABALTMON_8));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_9),
|
||||||
|
+ wstr_utf8 (_NL_WABALTMON_9));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_10),
|
||||||
|
+ wstr_utf8 (_NL_WABALTMON_10));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_11),
|
||||||
|
+ wstr_utf8 (_NL_WABALTMON_11));
|
||||||
|
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_12),
|
||||||
|
+ wstr_utf8 (_NL_WABALTMON_12));
|
||||||
|
+
|
||||||
|
+ /* LC_COLLATE. Mostly untested, only expected differences. */
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_COLLATE_CODESET), "ANSI_X3.4-1968");
|
||||||
|
+ TEST_COMPARE_STRING (str_utf8 (_NL_COLLATE_CODESET), "UTF-8");
|
||||||
|
+
|
||||||
|
+ /* LC_CTYPE. Mostly untested, only expected differences. */
|
||||||
|
+ TEST_COMPARE_STRING (str (CODESET), "ANSI_X3.4-1968");
|
||||||
|
+ TEST_COMPARE_STRING (str_utf8 (CODESET), "UTF-8");
|
||||||
|
+
|
||||||
|
+ /* LC_MONETARY. */
|
||||||
|
+ TEST_COMPARE_STRING (str (INT_CURR_SYMBOL), str_utf8 (INT_CURR_SYMBOL));
|
||||||
|
+ TEST_COMPARE_STRING (str (CURRENCY_SYMBOL), str_utf8 (CURRENCY_SYMBOL));
|
||||||
|
+ TEST_COMPARE_STRING (str (MON_DECIMAL_POINT), str_utf8 (MON_DECIMAL_POINT));
|
||||||
|
+ TEST_COMPARE_STRING (str (MON_THOUSANDS_SEP), str_utf8 (MON_THOUSANDS_SEP));
|
||||||
|
+ TEST_COMPARE_STRING (str (MON_GROUPING), str_utf8 (MON_GROUPING));
|
||||||
|
+ TEST_COMPARE_STRING (str (POSITIVE_SIGN), str_utf8 (POSITIVE_SIGN));
|
||||||
|
+ TEST_COMPARE_STRING (str (NEGATIVE_SIGN), str_utf8 (NEGATIVE_SIGN));
|
||||||
|
+ TEST_COMPARE (byte (INT_FRAC_DIGITS), byte_utf8 (INT_FRAC_DIGITS));
|
||||||
|
+ TEST_COMPARE (byte (FRAC_DIGITS), byte_utf8 (FRAC_DIGITS));
|
||||||
|
+ TEST_COMPARE (byte (P_CS_PRECEDES), byte_utf8 (P_CS_PRECEDES));
|
||||||
|
+ TEST_COMPARE (byte (P_SEP_BY_SPACE), byte_utf8 (P_SEP_BY_SPACE));
|
||||||
|
+ TEST_COMPARE (byte (N_CS_PRECEDES), byte_utf8 (N_CS_PRECEDES));
|
||||||
|
+ TEST_COMPARE (byte (N_SEP_BY_SPACE), byte_utf8 (N_SEP_BY_SPACE));
|
||||||
|
+ TEST_COMPARE (byte (P_SIGN_POSN), byte_utf8 (P_SIGN_POSN));
|
||||||
|
+ TEST_COMPARE (byte (N_SIGN_POSN), byte_utf8 (N_SIGN_POSN));
|
||||||
|
+ TEST_COMPARE_STRING (str (CRNCYSTR), str_utf8 (CRNCYSTR));
|
||||||
|
+ TEST_COMPARE (byte (INT_P_CS_PRECEDES), byte_utf8 (INT_P_CS_PRECEDES));
|
||||||
|
+ TEST_COMPARE (byte (INT_P_SEP_BY_SPACE), byte_utf8 (INT_P_SEP_BY_SPACE));
|
||||||
|
+ TEST_COMPARE (byte (INT_N_CS_PRECEDES), byte_utf8 (INT_N_CS_PRECEDES));
|
||||||
|
+ TEST_COMPARE (byte (INT_N_SEP_BY_SPACE), byte_utf8 (INT_N_SEP_BY_SPACE));
|
||||||
|
+ TEST_COMPARE (byte (INT_P_SIGN_POSN), byte_utf8 (INT_P_SIGN_POSN));
|
||||||
|
+ TEST_COMPARE (byte (INT_N_SIGN_POSN), byte_utf8 (INT_N_SIGN_POSN));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_MONETARY_DUO_INT_CURR_SYMBOL),
|
||||||
|
+ str_utf8 (_NL_MONETARY_DUO_INT_CURR_SYMBOL));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_MONETARY_DUO_CURRENCY_SYMBOL),
|
||||||
|
+ str_utf8 (_NL_MONETARY_DUO_CURRENCY_SYMBOL));
|
||||||
|
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_FRAC_DIGITS),
|
||||||
|
+ byte_utf8 (_NL_MONETARY_DUO_INT_FRAC_DIGITS));
|
||||||
|
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_FRAC_DIGITS),
|
||||||
|
+ byte_utf8 (_NL_MONETARY_DUO_FRAC_DIGITS));
|
||||||
|
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_P_CS_PRECEDES),
|
||||||
|
+ byte_utf8 (_NL_MONETARY_DUO_P_CS_PRECEDES));
|
||||||
|
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_P_SEP_BY_SPACE),
|
||||||
|
+ byte_utf8 (_NL_MONETARY_DUO_P_SEP_BY_SPACE));
|
||||||
|
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_N_CS_PRECEDES),
|
||||||
|
+ byte_utf8 (_NL_MONETARY_DUO_N_CS_PRECEDES));
|
||||||
|
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_N_SEP_BY_SPACE),
|
||||||
|
+ byte_utf8 (_NL_MONETARY_DUO_N_SEP_BY_SPACE));
|
||||||
|
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_P_CS_PRECEDES),
|
||||||
|
+ byte_utf8 (_NL_MONETARY_DUO_INT_P_CS_PRECEDES));
|
||||||
|
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_P_SEP_BY_SPACE),
|
||||||
|
+ byte_utf8 (_NL_MONETARY_DUO_INT_P_SEP_BY_SPACE));
|
||||||
|
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_N_CS_PRECEDES),
|
||||||
|
+ byte_utf8 (_NL_MONETARY_DUO_INT_N_CS_PRECEDES));
|
||||||
|
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_N_SEP_BY_SPACE),
|
||||||
|
+ byte_utf8 (_NL_MONETARY_DUO_INT_N_SEP_BY_SPACE));
|
||||||
|
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_P_SIGN_POSN),
|
||||||
|
+ byte_utf8 (_NL_MONETARY_DUO_INT_P_SIGN_POSN));
|
||||||
|
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_N_SIGN_POSN),
|
||||||
|
+ byte_utf8 (_NL_MONETARY_DUO_INT_N_SIGN_POSN));
|
||||||
|
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_P_SIGN_POSN),
|
||||||
|
+ byte_utf8 (_NL_MONETARY_DUO_P_SIGN_POSN));
|
||||||
|
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_N_SIGN_POSN),
|
||||||
|
+ byte_utf8 (_NL_MONETARY_DUO_N_SIGN_POSN));
|
||||||
|
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_P_SIGN_POSN),
|
||||||
|
+ byte_utf8 (_NL_MONETARY_DUO_INT_P_SIGN_POSN));
|
||||||
|
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_N_SIGN_POSN),
|
||||||
|
+ byte_utf8 (_NL_MONETARY_DUO_INT_N_SIGN_POSN));
|
||||||
|
+ TEST_COMPARE (word (_NL_MONETARY_UNO_VALID_FROM),
|
||||||
|
+ word_utf8 (_NL_MONETARY_UNO_VALID_FROM));
|
||||||
|
+ TEST_COMPARE (word (_NL_MONETARY_UNO_VALID_TO),
|
||||||
|
+ word_utf8 (_NL_MONETARY_UNO_VALID_TO));
|
||||||
|
+ TEST_COMPARE (word (_NL_MONETARY_DUO_VALID_FROM),
|
||||||
|
+ word_utf8 (_NL_MONETARY_DUO_VALID_FROM));
|
||||||
|
+ TEST_COMPARE (word (_NL_MONETARY_DUO_VALID_TO),
|
||||||
|
+ word_utf8 (_NL_MONETARY_DUO_VALID_TO));
|
||||||
|
+ /* _NL_MONETARY_CONVERSION_RATE cannot be tested (word array). */
|
||||||
|
+ TEST_COMPARE (word (_NL_MONETARY_DECIMAL_POINT_WC),
|
||||||
|
+ word_utf8 (_NL_MONETARY_DECIMAL_POINT_WC));
|
||||||
|
+ TEST_COMPARE (word (_NL_MONETARY_THOUSANDS_SEP_WC),
|
||||||
|
+ word_utf8 (_NL_MONETARY_THOUSANDS_SEP_WC));
|
||||||
|
+ /* Expected difference. */
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_MONETARY_CODESET), "ANSI_X3.4-1968");
|
||||||
|
+ TEST_COMPARE_STRING (str_utf8 (_NL_MONETARY_CODESET), "UTF-8");
|
||||||
|
+
|
||||||
|
+ /* LC_NUMERIC. */
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE_STRING (str (DECIMAL_POINT), str_utf8 (DECIMAL_POINT));
|
||||||
|
+ TEST_COMPARE_STRING (str (RADIXCHAR), str_utf8 (RADIXCHAR));
|
||||||
|
+ TEST_COMPARE_STRING (str (THOUSANDS_SEP), str_utf8 (THOUSANDS_SEP));
|
||||||
|
+ TEST_COMPARE_STRING (str (THOUSEP), str_utf8 (THOUSEP));
|
||||||
|
+ TEST_COMPARE_STRING (str (GROUPING), str_utf8 (GROUPING));
|
||||||
|
+ TEST_COMPARE (word (_NL_NUMERIC_DECIMAL_POINT_WC),
|
||||||
|
+ word_utf8 (_NL_NUMERIC_DECIMAL_POINT_WC));
|
||||||
|
+ TEST_COMPARE (word (_NL_NUMERIC_THOUSANDS_SEP_WC),
|
||||||
|
+ word_utf8 (_NL_NUMERIC_THOUSANDS_SEP_WC));
|
||||||
|
+ /* Expected difference. */
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_NUMERIC_CODESET), "ANSI_X3.4-1968");
|
||||||
|
+ TEST_COMPARE_STRING (str_utf8 (_NL_NUMERIC_CODESET), "UTF-8");
|
||||||
|
+
|
||||||
|
+ /* LC_MESSAGES. */
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE_STRING (str (YESEXPR), str_utf8 (YESEXPR));
|
||||||
|
+ TEST_COMPARE_STRING (str (NOEXPR), str_utf8 (NOEXPR));
|
||||||
|
+ TEST_COMPARE_STRING (str (YESSTR), str_utf8 (YESSTR));
|
||||||
|
+ TEST_COMPARE_STRING (str (NOSTR), str_utf8 (NOSTR));
|
||||||
|
+ /* Expected difference. */
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_MESSAGES_CODESET), "ANSI_X3.4-1968");
|
||||||
|
+ TEST_COMPARE_STRING (str_utf8 (_NL_MESSAGES_CODESET), "UTF-8");
|
||||||
|
+
|
||||||
|
+ /* LC_PAPER. */
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE (word (_NL_PAPER_HEIGHT), word_utf8 (_NL_PAPER_HEIGHT));
|
||||||
|
+ TEST_COMPARE (word (_NL_PAPER_WIDTH), word_utf8 (_NL_PAPER_WIDTH));
|
||||||
|
+ /* Expected difference. */
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_PAPER_CODESET), "ANSI_X3.4-1968");
|
||||||
|
+ TEST_COMPARE_STRING (str_utf8 (_NL_PAPER_CODESET), "UTF-8");
|
||||||
|
+
|
||||||
|
+ /* LC_NAME. */
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_NAME_NAME_FMT),
|
||||||
|
+ str_utf8 (_NL_NAME_NAME_FMT));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_NAME_NAME_GEN),
|
||||||
|
+ str_utf8 (_NL_NAME_NAME_GEN));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_NAME_NAME_MR),
|
||||||
|
+ str_utf8 (_NL_NAME_NAME_MR));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_NAME_NAME_MRS),
|
||||||
|
+ str_utf8 (_NL_NAME_NAME_MRS));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_NAME_NAME_MISS),
|
||||||
|
+ str_utf8 (_NL_NAME_NAME_MISS));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_NAME_NAME_MS),
|
||||||
|
+ str_utf8 (_NL_NAME_NAME_MS));
|
||||||
|
+ /* Expected difference. */
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_NAME_CODESET), "ANSI_X3.4-1968");
|
||||||
|
+ TEST_COMPARE_STRING (str_utf8 (_NL_NAME_CODESET), "UTF-8");
|
||||||
|
+
|
||||||
|
+ /* LC_ADDRESS. */
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_POSTAL_FMT),
|
||||||
|
+ str_utf8 (_NL_ADDRESS_POSTAL_FMT));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_COUNTRY_NAME),
|
||||||
|
+ str_utf8 (_NL_ADDRESS_COUNTRY_NAME));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_COUNTRY_POST),
|
||||||
|
+ str_utf8 (_NL_ADDRESS_COUNTRY_POST));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_COUNTRY_AB2),
|
||||||
|
+ str_utf8 (_NL_ADDRESS_COUNTRY_AB2));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_COUNTRY_AB3),
|
||||||
|
+ str_utf8 (_NL_ADDRESS_COUNTRY_AB3));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_COUNTRY_CAR),
|
||||||
|
+ str_utf8 (_NL_ADDRESS_COUNTRY_CAR));
|
||||||
|
+ TEST_COMPARE (word (_NL_ADDRESS_COUNTRY_NUM),
|
||||||
|
+ word_utf8 (_NL_ADDRESS_COUNTRY_NUM));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_COUNTRY_ISBN),
|
||||||
|
+ str_utf8 (_NL_ADDRESS_COUNTRY_ISBN));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_LANG_NAME),
|
||||||
|
+ str_utf8 (_NL_ADDRESS_LANG_NAME));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_LANG_AB),
|
||||||
|
+ str_utf8 (_NL_ADDRESS_LANG_AB));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_LANG_TERM),
|
||||||
|
+ str_utf8 (_NL_ADDRESS_LANG_TERM));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_LANG_LIB),
|
||||||
|
+ str_utf8 (_NL_ADDRESS_LANG_LIB));
|
||||||
|
+ /* Expected difference. */
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_CODESET), "ANSI_X3.4-1968");
|
||||||
|
+ TEST_COMPARE_STRING (str_utf8 (_NL_ADDRESS_CODESET), "UTF-8");
|
||||||
|
+
|
||||||
|
+ /* LC_TELEPHONE. */
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_TELEPHONE_TEL_INT_FMT),
|
||||||
|
+ str_utf8 (_NL_TELEPHONE_TEL_INT_FMT));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_TELEPHONE_TEL_DOM_FMT),
|
||||||
|
+ str_utf8 (_NL_TELEPHONE_TEL_DOM_FMT));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_TELEPHONE_INT_SELECT),
|
||||||
|
+ str_utf8 (_NL_TELEPHONE_INT_SELECT));
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_TELEPHONE_INT_PREFIX),
|
||||||
|
+ str_utf8 (_NL_TELEPHONE_INT_PREFIX));
|
||||||
|
+ /* Expected difference. */
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_TELEPHONE_CODESET), "ANSI_X3.4-1968");
|
||||||
|
+ TEST_COMPARE_STRING (str_utf8 (_NL_TELEPHONE_CODESET), "UTF-8");
|
||||||
|
+
|
||||||
|
+ /* LC_MEASUREMENT. */
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE (byte (_NL_MEASUREMENT_MEASUREMENT),
|
||||||
|
+ byte_utf8 (_NL_MEASUREMENT_MEASUREMENT));
|
||||||
|
+ /* Expected difference. */
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_MEASUREMENT_CODESET), "ANSI_X3.4-1968");
|
||||||
|
+ TEST_COMPARE_STRING (str_utf8 (_NL_MEASUREMENT_CODESET), "UTF-8");
|
||||||
|
+
|
||||||
|
+ /* LC_IDENTIFICATION is skipped since C.UTF-8 is distinct from C. */
|
||||||
|
+
|
||||||
|
+ /* _NL_IDENTIFICATION_CATEGORY cannot be tested because it is a
|
||||||
|
+ string array. */
|
||||||
|
+ /* Expected difference. */
|
||||||
|
+ TEST_COMPARE_STRING (str (_NL_IDENTIFICATION_CODESET), "ANSI_X3.4-1968");
|
||||||
|
+ TEST_COMPARE_STRING (str_utf8 (_NL_IDENTIFICATION_CODESET), "UTF-8");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ puts ("info: using setlocale and nl_langinfo");
|
||||||
|
+ one_pass ();
|
||||||
|
+
|
||||||
|
+ puts ("info: using nl_langinfo_l");
|
||||||
|
+
|
||||||
|
+ c_utf8 = newlocale (LC_ALL_MASK, "C.UTF-8", (locale_t) 0);
|
||||||
|
+ TEST_VERIFY_EXIT (c_utf8 != (locale_t) 0);
|
||||||
|
+
|
||||||
|
+ switch_to_c ();
|
||||||
|
+ use_nl_langinfo_l = true;
|
||||||
|
+ one_pass ();
|
||||||
|
+
|
||||||
|
+ freelocale (c_utf8);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
@ -1,286 +0,0 @@
|
|||||||
Short description: Add C.UTF-8 support.
|
|
||||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
|
||||||
Origin: PATCH
|
|
||||||
Upstream status: not-submitted
|
|
||||||
|
|
||||||
This patch needs to upstream as part of Carlos O'Donell
|
|
||||||
<carlos@redhat.com>'s work on enabling upstream C.UTF-8 support. This
|
|
||||||
work is currently blocked on cleaning up the test results to prove that
|
|
||||||
full code-point sorting is working as intended.
|
|
||||||
|
|
||||||
Note that this patch does not provide full code-point sorting as
|
|
||||||
expected.
|
|
||||||
|
|
||||||
This patch needs to upstream as soon as possible since it would be nice
|
|
||||||
to have this in F29 and fixed.
|
|
||||||
|
|
||||||
From 2eda7b462b415105f5a05c1323372d4e39d46439 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Mike FABIAN <mfabian@redhat.com>
|
|
||||||
Date: Mon, 10 Aug 2015 15:58:12 +0200
|
|
||||||
Subject: [PATCH] Add a C.UTF-8 locale
|
|
||||||
|
|
||||||
---
|
|
||||||
localedata/SUPPORTED | 1 +
|
|
||||||
localedata/locales/C | 238 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
2 files changed, 239 insertions(+)
|
|
||||||
create mode 100644 localedata/locales/C
|
|
||||||
|
|
||||||
diff --git a/localedata/SUPPORTED b/localedata/SUPPORTED
|
|
||||||
index 8ca023e..2a78391 100644
|
|
||||||
--- a/localedata/SUPPORTED
|
|
||||||
+++ b/localedata/SUPPORTED
|
|
||||||
@@ -1,6 +1,7 @@
|
|
||||||
# This file names the currently supported and somewhat tested locales.
|
|
||||||
# If you have any additions please file a glibc bug report.
|
|
||||||
SUPPORTED-LOCALES=\
|
|
||||||
+C.UTF-8/UTF-8 \
|
|
||||||
aa_DJ.UTF-8/UTF-8 \
|
|
||||||
aa_DJ/ISO-8859-1 \
|
|
||||||
aa_ER/UTF-8 \
|
|
||||||
diff --git a/localedata/locales/C b/localedata/locales/C
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..fdf460e
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/localedata/locales/C
|
|
||||||
@@ -0,0 +1,238 @@
|
|
||||||
+escape_char /
|
|
||||||
+comment_char %
|
|
||||||
+% Locale for C locale in UTF-8
|
|
||||||
+
|
|
||||||
+LC_IDENTIFICATION
|
|
||||||
+title "C locale"
|
|
||||||
+source ""
|
|
||||||
+address ""
|
|
||||||
+contact ""
|
|
||||||
+email "mfabian@redhat.com"
|
|
||||||
+tel ""
|
|
||||||
+fax ""
|
|
||||||
+language "C"
|
|
||||||
+territory ""
|
|
||||||
+revision "1.0"
|
|
||||||
+date "2015-08-10"
|
|
||||||
+%
|
|
||||||
+category "i18n:2012";LC_IDENTIFICATION
|
|
||||||
+category "i18n:2012";LC_CTYPE
|
|
||||||
+category "i18n:2012";LC_COLLATE
|
|
||||||
+category "i18n:2012";LC_TIME
|
|
||||||
+category "i18n:2012";LC_NUMERIC
|
|
||||||
+category "i18n:2012";LC_MONETARY
|
|
||||||
+category "i18n:2012";LC_MESSAGES
|
|
||||||
+category "i18n:2012";LC_PAPER
|
|
||||||
+category "i18n:2012";LC_NAME
|
|
||||||
+category "i18n:2012";LC_ADDRESS
|
|
||||||
+category "i18n:2012";LC_TELEPHONE
|
|
||||||
+category "i18n:2012";LC_MEASUREMENT
|
|
||||||
+END LC_IDENTIFICATION
|
|
||||||
+
|
|
||||||
+LC_CTYPE
|
|
||||||
+copy "i18n"
|
|
||||||
+
|
|
||||||
+translit_start
|
|
||||||
+include "translit_combining";""
|
|
||||||
+translit_end
|
|
||||||
+
|
|
||||||
+END LC_CTYPE
|
|
||||||
+
|
|
||||||
+LC_COLLATE
|
|
||||||
+order_start forward
|
|
||||||
+<U0000>
|
|
||||||
+..
|
|
||||||
+<UFFFF>
|
|
||||||
+<U10000>
|
|
||||||
+..
|
|
||||||
+<U1FFFF>
|
|
||||||
+<U20000>
|
|
||||||
+..
|
|
||||||
+<U2FFFF>
|
|
||||||
+<UE0000>
|
|
||||||
+..
|
|
||||||
+<UEFFFF>
|
|
||||||
+<UF0000>
|
|
||||||
+..
|
|
||||||
+<UFFFFF>
|
|
||||||
+<U100000>
|
|
||||||
+..
|
|
||||||
+<U10FFFF>
|
|
||||||
+UNDEFINED
|
|
||||||
+order_end
|
|
||||||
+END LC_COLLATE
|
|
||||||
+
|
|
||||||
+LC_MONETARY
|
|
||||||
+% This is the 14652 i18n fdcc-set definition for
|
|
||||||
+% the LC_MONETARY category
|
|
||||||
+% (except for the int_curr_symbol and currency_symbol, they are empty in
|
|
||||||
+% the 14652 i18n fdcc-set definition and also empty in
|
|
||||||
+% glibc/locale/C-monetary.c. But localedef complains in that case).
|
|
||||||
+%
|
|
||||||
+% Using "USD" for int_curr_symbol. But maybe "XXX" would be better?
|
|
||||||
+% XXX is "No currency" (https://en.wikipedia.org/wiki/ISO_4217)
|
|
||||||
+int_curr_symbol "<U0055><U0053><U0044><U0020>"
|
|
||||||
+% Using "$" for currency_symbol. But maybe <U00A4> would be better?
|
|
||||||
+% U+00A4 is the "generic currency symbol"
|
|
||||||
+% (https://en.wikipedia.org/wiki/Currency_sign_%28typography%29)
|
|
||||||
+currency_symbol "<U0024>"
|
|
||||||
+mon_decimal_point "<U002E>"
|
|
||||||
+mon_thousands_sep ""
|
|
||||||
+mon_grouping -1
|
|
||||||
+positive_sign ""
|
|
||||||
+negative_sign "<U002D>"
|
|
||||||
+int_frac_digits -1
|
|
||||||
+frac_digits -1
|
|
||||||
+p_cs_precedes -1
|
|
||||||
+int_p_sep_by_space -1
|
|
||||||
+p_sep_by_space -1
|
|
||||||
+n_cs_precedes -1
|
|
||||||
+int_n_sep_by_space -1
|
|
||||||
+n_sep_by_space -1
|
|
||||||
+p_sign_posn -1
|
|
||||||
+n_sign_posn -1
|
|
||||||
+%
|
|
||||||
+END LC_MONETARY
|
|
||||||
+
|
|
||||||
+LC_NUMERIC
|
|
||||||
+% This is the POSIX Locale definition for
|
|
||||||
+% the LC_NUMERIC category.
|
|
||||||
+%
|
|
||||||
+decimal_point "<U002E>"
|
|
||||||
+thousands_sep ""
|
|
||||||
+grouping -1
|
|
||||||
+END LC_NUMERIC
|
|
||||||
+
|
|
||||||
+LC_TIME
|
|
||||||
+% This is the POSIX Locale definition for
|
|
||||||
+% the LC_TIME category.
|
|
||||||
+%
|
|
||||||
+% Abbreviated weekday names (%a)
|
|
||||||
+abday "<U0053><U0075><U006E>";"<U004D><U006F><U006E>";/
|
|
||||||
+ "<U0054><U0075><U0065>";"<U0057><U0065><U0064>";/
|
|
||||||
+ "<U0054><U0068><U0075>";"<U0046><U0072><U0069>";/
|
|
||||||
+ "<U0053><U0061><U0074>"
|
|
||||||
+
|
|
||||||
+% Full weekday names (%A)
|
|
||||||
+day "<U0053><U0075><U006E><U0064><U0061><U0079>";/
|
|
||||||
+ "<U004D><U006F><U006E><U0064><U0061><U0079>";/
|
|
||||||
+ "<U0054><U0075><U0065><U0073><U0064><U0061><U0079>";/
|
|
||||||
+ "<U0057><U0065><U0064><U006E><U0065><U0073><U0064><U0061><U0079>";/
|
|
||||||
+ "<U0054><U0068><U0075><U0072><U0073><U0064><U0061><U0079>";/
|
|
||||||
+ "<U0046><U0072><U0069><U0064><U0061><U0079>";/
|
|
||||||
+ "<U0053><U0061><U0074><U0075><U0072><U0064><U0061><U0079>"
|
|
||||||
+
|
|
||||||
+% Abbreviated month names (%b)
|
|
||||||
+abmon "<U004A><U0061><U006E>";"<U0046><U0065><U0062>";/
|
|
||||||
+ "<U004D><U0061><U0072>";"<U0041><U0070><U0072>";/
|
|
||||||
+ "<U004D><U0061><U0079>";"<U004A><U0075><U006E>";/
|
|
||||||
+ "<U004A><U0075><U006C>";"<U0041><U0075><U0067>";/
|
|
||||||
+ "<U0053><U0065><U0070>";"<U004F><U0063><U0074>";/
|
|
||||||
+ "<U004E><U006F><U0076>";"<U0044><U0065><U0063>"
|
|
||||||
+
|
|
||||||
+% Full month names (%B)
|
|
||||||
+mon "<U004A><U0061><U006E><U0075><U0061><U0072><U0079>";/
|
|
||||||
+ "<U0046><U0065><U0062><U0072><U0075><U0061><U0072><U0079>";/
|
|
||||||
+ "<U004D><U0061><U0072><U0063><U0068>";/
|
|
||||||
+ "<U0041><U0070><U0072><U0069><U006C>";/
|
|
||||||
+ "<U004D><U0061><U0079>";/
|
|
||||||
+ "<U004A><U0075><U006E><U0065>";/
|
|
||||||
+ "<U004A><U0075><U006C><U0079>";/
|
|
||||||
+ "<U0041><U0075><U0067><U0075><U0073><U0074>";/
|
|
||||||
+ "<U0053><U0065><U0070><U0074><U0065><U006D><U0062><U0065><U0072>";/
|
|
||||||
+ "<U004F><U0063><U0074><U006F><U0062><U0065><U0072>";/
|
|
||||||
+ "<U004E><U006F><U0076><U0065><U006D><U0062><U0065><U0072>";/
|
|
||||||
+ "<U0044><U0065><U0063><U0065><U006D><U0062><U0065><U0072>"
|
|
||||||
+
|
|
||||||
+% Week description, consists of three fields:
|
|
||||||
+% 1. Number of days in a week.
|
|
||||||
+% 2. Gregorian date that is a first weekday (19971130 for Sunday, 19971201 for Monday).
|
|
||||||
+% 3. The weekday number to be contained in the first week of the year.
|
|
||||||
+%
|
|
||||||
+% ISO 8601 conforming applications should use the values 7, 19971201 (a
|
|
||||||
+% Monday), and 4 (Thursday), respectively.
|
|
||||||
+week 7;19971201;4
|
|
||||||
+first_weekday 1
|
|
||||||
+first_workday 1
|
|
||||||
+
|
|
||||||
+% Appropriate date and time representation (%c)
|
|
||||||
+% "%a %b %e %H:%M:%S %Y"
|
|
||||||
+d_t_fmt "<U0025><U0061><U0020><U0025><U0062><U0020><U0025><U0065><U0020><U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U0059>"
|
|
||||||
+
|
|
||||||
+% Appropriate date representation (%x)
|
|
||||||
+% "%m/%d/%y"
|
|
||||||
+d_fmt "<U0025><U006D><U002F><U0025><U0064><U002F><U0025><U0079>"
|
|
||||||
+
|
|
||||||
+% Appropriate time representation (%X)
|
|
||||||
+% "%H:%M:%S"
|
|
||||||
+t_fmt "<U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053>"
|
|
||||||
+
|
|
||||||
+% Appropriate AM/PM time representation (%r)
|
|
||||||
+% "%I:%M:%S %p"
|
|
||||||
+t_fmt_ampm "<U0025><U0049><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U0070>"
|
|
||||||
+
|
|
||||||
+% Equivalent of AM/PM (%p) "AM"/"PM"
|
|
||||||
+%
|
|
||||||
+am_pm "<U0041><U004D>";"<U0050><U004D>"
|
|
||||||
+
|
|
||||||
+% Appropriate date representation (date(1)) "%a %b %e %H:%M:%S %Z %Y"
|
|
||||||
+date_fmt "<U0025><U0061><U0020><U0025><U0062><U0020><U0025><U0065><U0020><U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A><U0020><U0025><U0059>"
|
|
||||||
+END LC_TIME
|
|
||||||
+
|
|
||||||
+LC_MESSAGES
|
|
||||||
+% This is the POSIX Locale definition for
|
|
||||||
+% the LC_NUMERIC category.
|
|
||||||
+%
|
|
||||||
+yesexpr "<U005E><U005B><U0079><U0059><U005D>"
|
|
||||||
+noexpr "<U005E><U005B><U006E><U004E><U005D>"
|
|
||||||
+yesstr "<U0059><U0065><U0073>"
|
|
||||||
+nostr "<U004E><U006F>"
|
|
||||||
+END LC_MESSAGES
|
|
||||||
+
|
|
||||||
+LC_PAPER
|
|
||||||
+% This is the ISO/IEC 14652 "i18n" definition for
|
|
||||||
+% the LC_PAPER category.
|
|
||||||
+% (A4 paper, this is also used in the built in C/POSIX
|
|
||||||
+% locale in glibc/locale/C-paper.c)
|
|
||||||
+height 297
|
|
||||||
+width 210
|
|
||||||
+END LC_PAPER
|
|
||||||
+
|
|
||||||
+LC_NAME
|
|
||||||
+% This is the ISO/IEC 14652 "i18n" definition for
|
|
||||||
+% the LC_NAME category.
|
|
||||||
+% "%p%t%g%t%m%t%f"
|
|
||||||
+% (also used in the built in C/POSIX locale in glibc/locale/C-name.c)
|
|
||||||
+name_fmt "<U0025><U0070><U0025><U0074><U0025><U0067><U0025><U0074>/
|
|
||||||
+<U0025><U006D><U0025><U0074><U0025><U0066>"
|
|
||||||
+END LC_NAME
|
|
||||||
+
|
|
||||||
+LC_ADDRESS
|
|
||||||
+% This is the ISO/IEC 14652 "i18n" definition for
|
|
||||||
+% the LC_ADDRESS category.
|
|
||||||
+% "%a%N%f%N%d%N%b%N%s %h %e %r%N%C-%z %T%N%c%N"
|
|
||||||
+% (also used in the built in C/POSIX locale in glibc/locale/C-address.c)
|
|
||||||
+postal_fmt "<U0025><U0061><U0025><U004E><U0025><U0066><U0025><U004E>/
|
|
||||||
+<U0025><U0064><U0025><U004E><U0025><U0062><U0025><U004E><U0025><U0073>/
|
|
||||||
+<U0020><U0025><U0068><U0020><U0025><U0065><U0020><U0025><U0072><U0025>/
|
|
||||||
+<U004E><U0025><U0043><U002D><U0025><U007A><U0020><U0025><U0054><U0025>/
|
|
||||||
+<U004E><U0025><U0063><U0025><U004E>"
|
|
||||||
+END LC_ADDRESS
|
|
||||||
+
|
|
||||||
+LC_TELEPHONE
|
|
||||||
+% This is the ISO/IEC 14652 "i18n" definition for
|
|
||||||
+% the LC_TELEPHONE category.
|
|
||||||
+% "+%c %a %l"
|
|
||||||
+tel_int_fmt "<U002B><U0025><U0063><U0020><U0025><U0061><U0020><U0025>/
|
|
||||||
+<U006C>"
|
|
||||||
+% (also used in the built in C/POSIX locale in glibc/locale/C-telephone.c)
|
|
||||||
+END LC_TELEPHONE
|
|
||||||
+
|
|
||||||
+LC_MEASUREMENT
|
|
||||||
+% This is the ISO/IEC 14652 "i18n" definition for
|
|
||||||
+% the LC_MEASUREMENT category.
|
|
||||||
+% (same as in the built in C/POSIX locale in glibc/locale/C-measurement.c)
|
|
||||||
+%metric
|
|
||||||
+measurement 1
|
|
||||||
+END LC_MEASUREMENT
|
|
||||||
+
|
|
||||||
--
|
|
||||||
2.4.3
|
|
||||||
|
|
@ -1,15 +1,44 @@
|
|||||||
Short description: Adjust CS_PATH return value.
|
Short description: Adjust CS_PATH and the test container layout.
|
||||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||||
Origin: PATCH
|
Origin: PATCH
|
||||||
Upstream status: not-needed
|
Upstream status: not-needed
|
||||||
|
|
||||||
In Fedora we should return only /usr/bin because /bin is just a symlink
|
In Fedora we should return only /usr/bin as CS_PATH because /bin is just
|
||||||
to /usr/bin after MoveToUsr transition (which glibc has not really
|
a symlink to /usr/bin after MoveToUsr transition (which glibc has not
|
||||||
completed).
|
really completed).
|
||||||
|
|
||||||
diff -pruN a/sysdeps/unix/confstr.h b/sysdeps/unix/confstr.h
|
We also create /{bin,lib,lib64,sbin} in the test container as symbolic
|
||||||
--- a/sysdeps/unix/confstr.h 2012-12-25 08:32:13.000000000 +0530
|
links. This brings the test container in line with Fedora's filesystem
|
||||||
+++ b/sysdeps/unix/confstr.h 2014-09-05 20:02:55.698275219 +0530
|
layout and avoids some test failures. For example, because Fedora's
|
||||||
|
CS_PATH is /usr/bin, tst-vfork3 will try to execute /usr/bin/echo in the
|
||||||
|
container. Without this change the container installs `echo' in /bin
|
||||||
|
not /usr/bin, causing the test to fail.
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index a49870d3d1e636a9..feb2599203b10098 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -598,9 +598,13 @@ $(tests-container) $(addsuffix /tests,$(subdirs)) : \
|
||||||
|
$(objpfx)testroot.pristine/install.stamp :
|
||||||
|
test -d $(objpfx)testroot.pristine || \
|
||||||
|
mkdir $(objpfx)testroot.pristine
|
||||||
|
- # We need a working /bin/sh for some of the tests.
|
||||||
|
- test -d $(objpfx)testroot.pristine/bin || \
|
||||||
|
- mkdir $(objpfx)testroot.pristine/bin
|
||||||
|
+ # Set up symlinks to directories whose contents got moved to /usr
|
||||||
|
+ for moved in bin lib lib64 sbin; do \
|
||||||
|
+ test -d $(objpfx)testroot.pristine/usr/$$moved || \
|
||||||
|
+ mkdir -p $(objpfx)testroot.pristine/usr/$$moved ;\
|
||||||
|
+ test -e $(objpfx)testroot.pristine/$$moved || \
|
||||||
|
+ ln -s usr/$$moved $(objpfx)testroot.pristine/$$moved ;\
|
||||||
|
+ done
|
||||||
|
# We need the compiled locale dir for localedef tests.
|
||||||
|
test -d $(objpfx)testroot.pristine/$(complocaledir) || \
|
||||||
|
mkdir -p $(objpfx)testroot.pristine/$(complocaledir)
|
||||||
|
diff --git a/sysdeps/unix/confstr.h b/sysdeps/unix/confstr.h
|
||||||
|
index 15859c3b2759878e..9b63b7f8069866fd 100644
|
||||||
|
--- a/sysdeps/unix/confstr.h
|
||||||
|
+++ b/sysdeps/unix/confstr.h
|
||||||
@@ -1 +1 @@
|
@@ -1 +1 @@
|
||||||
-#define CS_PATH "/bin:/usr/bin"
|
-#define CS_PATH "/bin:/usr/bin"
|
||||||
+#define CS_PATH "/usr/bin"
|
+#define CS_PATH "/usr/bin"
|
||||||
|
20
SOURCES/glibc-deprecated-selinux-makedb.patch
Normal file
20
SOURCES/glibc-deprecated-selinux-makedb.patch
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
This is necessary to get things building again after libselinux changes.
|
||||||
|
A proper fix is under discussion upstream:
|
||||||
|
|
||||||
|
<https://sourceware.org/pipermail/libc-alpha/2020-July/116504.html>
|
||||||
|
|
||||||
|
diff --git a/nss/makedb.c b/nss/makedb.c
|
||||||
|
index 8e389a1683747cf1..9d81aed57d384a22 100644
|
||||||
|
--- a/nss/makedb.c
|
||||||
|
+++ b/nss/makedb.c
|
||||||
|
@@ -17,6 +17,10 @@
|
||||||
|
License along with the GNU C Library; if not, see
|
||||||
|
<https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
+/* This file uses deprecated declarations from libselinux. */
|
||||||
|
+#include <libc-diag.h>
|
||||||
|
+DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wdeprecated-declarations");
|
||||||
|
+
|
||||||
|
#include <argp.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
17
SOURCES/glibc-deprecated-selinux-nscd.patch
Normal file
17
SOURCES/glibc-deprecated-selinux-nscd.patch
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
This patch works around deprecated libselinux features used by nscd.
|
||||||
|
|
||||||
|
diff --git a/nscd/selinux.c b/nscd/selinux.c
|
||||||
|
index a4ea8008e201b939..0acca4639202a75a 100644
|
||||||
|
--- a/nscd/selinux.c
|
||||||
|
+++ b/nscd/selinux.c
|
||||||
|
@@ -17,6 +17,10 @@
|
||||||
|
License along with the GNU C Library; if not, see
|
||||||
|
<https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
+/* This file uses deprecated declarations from libselinux. */
|
||||||
|
+#include <libc-diag.h>
|
||||||
|
+DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wdeprecated-declarations");
|
||||||
|
+
|
||||||
|
#include "config.h"
|
||||||
|
#include <error.h>
|
||||||
|
#include <errno.h>
|
@ -1,91 +0,0 @@
|
|||||||
Short description: Cleanup use of _dl_starting_up.
|
|
||||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
|
||||||
Origin: PATCH
|
|
||||||
Upstream status: https://sourceware.org/ml/libc-alpha/2014-02/msg00589.html
|
|
||||||
|
|
||||||
Upstream discussions:
|
|
||||||
https://sourceware.org/ml/libc-alpha/2014-02/msg00580.html
|
|
||||||
|
|
||||||
Based on the following commit:
|
|
||||||
~~~
|
|
||||||
From 16552c01a66633c9e412984d9d92616bd4e5303c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Andreas Schwab <schwab@redhat.com>
|
|
||||||
Date: Fri, 11 Jun 2010 11:04:11 +0200
|
|
||||||
Subject: [PATCH] Properly set __libc_multiple_libcs
|
|
||||||
|
|
||||||
* elf/rtld.c (_dl_starting_up): Always define.
|
|
||||||
(dl_main): Always set _dl_starting_up.
|
|
||||||
* elf/dl-support.c (_dl_starting_up): Always define.
|
|
||||||
* elf/dl-init.c (_dl_init): Always clear _dl_starting_up.
|
|
||||||
|
|
||||||
---
|
|
||||||
ChangeLog | 7 +++++++
|
|
||||||
elf/dl-init.c | 4 ----
|
|
||||||
elf/dl-support.c | 2 --
|
|
||||||
elf/rtld.c | 4 ----
|
|
||||||
4 files changed, 7 insertions(+), 10 deletions(-)
|
|
||||||
~~~
|
|
||||||
|
|
||||||
This patch needs to go upstream to get cleaned up, but has always involed
|
|
||||||
analysis of the GNU/Hurd parts of the change and that stalled out, but
|
|
||||||
perhaps with build-many-glibcs we can now test these changes more easily.
|
|
||||||
|
|
||||||
Index: b/elf/dl-init.c
|
|
||||||
===================================================================
|
|
||||||
--- a/elf/dl-init.c
|
|
||||||
+++ b/elf/dl-init.c
|
|
||||||
@@ -119,8 +119,6 @@ _dl_init (struct link_map *main_map, int
|
|
||||||
while (i-- > 0)
|
|
||||||
call_init (main_map->l_initfini[i], argc, argv, env);
|
|
||||||
|
|
||||||
-#ifndef HAVE_INLINED_SYSCALLS
|
|
||||||
/* Finished starting up. */
|
|
||||||
_dl_starting_up = 0;
|
|
||||||
-#endif
|
|
||||||
}
|
|
||||||
Index: b/elf/dl-support.c
|
|
||||||
===================================================================
|
|
||||||
--- a/elf/dl-support.c
|
|
||||||
+++ b/elf/dl-support.c
|
|
||||||
@@ -117,10 +117,8 @@ struct r_scope_elem _dl_initial_searchli
|
|
||||||
.r_nlist = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
-#ifndef HAVE_INLINED_SYSCALLS
|
|
||||||
/* Nonzero during startup. */
|
|
||||||
int _dl_starting_up = 1;
|
|
||||||
-#endif
|
|
||||||
|
|
||||||
/* Random data provided by the kernel. */
|
|
||||||
void *_dl_random;
|
|
||||||
Index: b/elf/rtld.c
|
|
||||||
===================================================================
|
|
||||||
--- a/elf/rtld.c
|
|
||||||
+++ b/elf/rtld.c
|
|
||||||
@@ -214,7 +214,6 @@ audit_list_iter_next (struct audit_list_
|
|
||||||
return iter->previous->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
-#ifndef HAVE_INLINED_SYSCALLS
|
|
||||||
/* Set nonzero during loading and initialization of executable and
|
|
||||||
libraries, cleared before the executable's entry point runs. This
|
|
||||||
must not be initialized to nonzero, because the unused dynamic
|
|
||||||
@@ -224,7 +223,6 @@ audit_list_iter_next (struct audit_list_
|
|
||||||
never be called. */
|
|
||||||
int _dl_starting_up = 0;
|
|
||||||
rtld_hidden_def (_dl_starting_up)
|
|
||||||
-#endif
|
|
||||||
|
|
||||||
/* This is the structure which defines all variables global to ld.so
|
|
||||||
(except those which cannot be added for some reason). */
|
|
||||||
@@ -898,10 +896,8 @@ dl_main (const ElfW(Phdr) *phdr,
|
|
||||||
/* Process the environment variable which control the behaviour. */
|
|
||||||
process_envvars (&mode);
|
|
||||||
|
|
||||||
-#ifndef HAVE_INLINED_SYSCALLS
|
|
||||||
/* Set up a flag which tells we are just starting. */
|
|
||||||
_dl_starting_up = 1;
|
|
||||||
-#endif
|
|
||||||
|
|
||||||
if (*user_entry == (ElfW(Addr)) ENTRY_POINT)
|
|
||||||
{
|
|
@ -1,21 +0,0 @@
|
|||||||
Short description: Fedora-specific glibc install locale changes.
|
|
||||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
|
||||||
Origin: PATCH
|
|
||||||
Upstream status: not-needed
|
|
||||||
|
|
||||||
The Fedora glibc build and install does not need the normal install
|
|
||||||
behaviour which updates the locale archive. The Fedora install phase
|
|
||||||
in the spec file of the rpm will handle this manually.
|
|
||||||
|
|
||||||
diff --git a/localedata/Makefile b/localedata/Makefile
|
|
||||||
index a5f3c92d58954dfc..56719c7c714aa0f1 100644
|
|
||||||
--- a/localedata/Makefile
|
|
||||||
+++ b/localedata/Makefile
|
|
||||||
@@ -218,6 +218,7 @@ $(INSTALL-SUPPORTED-LOCALES): install-locales-dir
|
|
||||||
echo -n '...'; \
|
|
||||||
input=`echo $$locale | sed 's/\([^.]*\)[^@]*\(.*\)/\1\2/'`; \
|
|
||||||
$(LOCALEDEF) $$flags --alias-file=../intl/locale.alias \
|
|
||||||
+ --no-archive \
|
|
||||||
-i locales/$$input -f charmaps/$$charset \
|
|
||||||
$(addprefix --prefix=,$(install_root)) $$locale \
|
|
||||||
&& echo ' done'; \
|
|
@ -1,46 +0,0 @@
|
|||||||
Short description: Allow access to internal locale archive functions.
|
|
||||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
|
||||||
Origin: PATCH
|
|
||||||
Upstream status: not-needed
|
|
||||||
|
|
||||||
This is a part of commit glibc-2.3.3-1492-ga891c7b,
|
|
||||||
needed for fedora/build-locale-archive.c only.
|
|
||||||
|
|
||||||
2007-04-16 Jakub Jelinek <jakub@redhat.com>
|
|
||||||
|
|
||||||
* locale/programs/locarchive.c (add_alias, insert_name): Remove static.
|
|
||||||
|
|
||||||
diff -Nrup a/locale/programs/locarchive.c b/locale/programs/locarchive.c
|
|
||||||
--- a/locale/programs/locarchive.c 2012-06-05 07:42:49.000000000 -0600
|
|
||||||
+++ b/locale/programs/locarchive.c 2012-06-07 12:15:21.585319540 -0600
|
|
||||||
@@ -252,9 +252,9 @@ oldlocrecentcmp (const void *a, const vo
|
|
||||||
/* forward decls for below */
|
|
||||||
static uint32_t add_locale (struct locarhandle *ah, const char *name,
|
|
||||||
locale_data_t data, bool replace);
|
|
||||||
-static void add_alias (struct locarhandle *ah, const char *alias,
|
|
||||||
- bool replace, const char *oldname,
|
|
||||||
- uint32_t *locrec_offset_p);
|
|
||||||
+void add_alias (struct locarhandle *ah, const char *alias,
|
|
||||||
+ bool replace, const char *oldname,
|
|
||||||
+ uint32_t *locrec_offset_p);
|
|
||||||
|
|
||||||
|
|
||||||
static bool
|
|
||||||
@@ -635,7 +635,7 @@ close_archive (struct locarhandle *ah)
|
|
||||||
#include "../../intl/explodename.c"
|
|
||||||
#include "../../intl/l10nflist.c"
|
|
||||||
|
|
||||||
-static struct namehashent *
|
|
||||||
+struct namehashent *
|
|
||||||
insert_name (struct locarhandle *ah,
|
|
||||||
const char *name, size_t name_len, bool replace)
|
|
||||||
{
|
|
||||||
@@ -693,7 +693,7 @@ insert_name (struct locarhandle *ah,
|
|
||||||
return &namehashtab[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void
|
|
||||||
+void
|
|
||||||
add_alias (struct locarhandle *ah, const char *alias, bool replace,
|
|
||||||
const char *oldname, uint32_t *locrec_offset_p)
|
|
||||||
{
|
|
@ -1,31 +0,0 @@
|
|||||||
Short description: Fedora-specific enabling batch read in NSS.
|
|
||||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
|
||||||
Origin: PATCH
|
|
||||||
Bug-RHEL: #188246
|
|
||||||
Upstream status: not-submitted
|
|
||||||
|
|
||||||
Enable batch read in NSS. It's not clear if this is always a win or
|
|
||||||
just a win for NIS+, this needs to be analyzed and sent upstream or
|
|
||||||
removed.
|
|
||||||
|
|
||||||
From baba5d9461d4e8a581ac26fe4412ad783ffc73e7 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jakub Jelinek <jakub@redhat.com>
|
|
||||||
Date: Mon, 1 May 2006 08:02:53 +0000
|
|
||||||
Subject: [PATCH] Enable SETENT_BATCH_READ nis/nss option by default
|
|
||||||
|
|
||||||
* Mon May 1 2006 Jakub Jelinek <jakub@redhat.com> 2.4.90-4
|
|
||||||
- SETENT_BATCH_READ /etc/default/nss option for speeding up
|
|
||||||
some usages of NIS+ (#188246)
|
|
||||||
|
|
||||||
diff --git a/nis/nss b/nis/nss
|
|
||||||
--- a/nis/nss
|
|
||||||
+++ b/nis/nss
|
|
||||||
@@ -25,7 +25,7 @@
|
|
||||||
# memory with every getXXent() call. Otherwise each getXXent() call
|
|
||||||
# might result into a network communication with the server to get
|
|
||||||
# the next entry.
|
|
||||||
-#SETENT_BATCH_READ=TRUE
|
|
||||||
+SETENT_BATCH_READ=TRUE
|
|
||||||
#
|
|
||||||
# ADJUNCT_AS_SHADOW
|
|
||||||
# If set to TRUE, the passwd routines in the NIS NSS module will not
|
|
@ -1,6 +1,11 @@
|
|||||||
diff -Nrup a/nss/nsswitch.conf b/nss/nsswitch.conf
|
The Fedora /etc/nsswitch.conf is based largely on the upstream
|
||||||
--- a/nss/nsswitch.conf 2019-10-25 12:14:09.255834866 -0400
|
version with minor downstream distribution modifications for
|
||||||
+++ b/nss/nsswitch.conf 2019-10-25 12:50:08.425769248 -0400
|
use with SSSD and systemd.
|
||||||
|
|
||||||
|
diff --git a/nss/nsswitch.conf b/nss/nsswitch.conf
|
||||||
|
index 4a6bcb1f7bc0b1f4..980a68e32e6a04b8 100644
|
||||||
|
--- a/nss/nsswitch.conf
|
||||||
|
+++ b/nss/nsswitch.conf
|
||||||
@@ -1,7 +1,7 @@
|
@@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
# /etc/nsswitch.conf
|
# /etc/nsswitch.conf
|
||||||
@ -10,14 +15,14 @@ diff -Nrup a/nss/nsswitch.conf b/nss/nsswitch.conf
|
|||||||
# sorted with the most-used services at the beginning.
|
# sorted with the most-used services at the beginning.
|
||||||
#
|
#
|
||||||
# Valid databases are: aliases, ethers, group, gshadow, hosts,
|
# Valid databases are: aliases, ethers, group, gshadow, hosts,
|
||||||
@@ -52,18 +52,20 @@
|
@@ -52,19 +52,21 @@
|
||||||
# shadow: db files
|
# shadow: db files
|
||||||
# group: db files
|
# group: db files
|
||||||
|
|
||||||
-# In alphabetical order. Re-order as required to optimize peformance.
|
-# In alphabetical order. Re-order as required to optimize peformance.
|
||||||
+# In order of likelihood of use to accelerate lookup.
|
+# In order of likelihood of use to accelerate lookup.
|
||||||
+passwd: sss files
|
+passwd: sss files
|
||||||
+shadow: files sss
|
+shadow: files
|
||||||
+group: sss files
|
+group: sss files
|
||||||
+hosts: files dns myhostname
|
+hosts: files dns myhostname
|
||||||
+services: files sss
|
+services: files sss
|
||||||
@ -29,7 +34,8 @@ diff -Nrup a/nss/nsswitch.conf b/nss/nsswitch.conf
|
|||||||
-group: files
|
-group: files
|
||||||
gshadow: files
|
gshadow: files
|
||||||
-hosts: files dns
|
-hosts: files dns
|
||||||
initgroups: files
|
# Allow initgroups to default to the setting for group.
|
||||||
|
# initgroups: files
|
||||||
-netgroup: files
|
-netgroup: files
|
||||||
networks: files dns
|
networks: files dns
|
||||||
-passwd: files
|
-passwd: files
|
@ -1,38 +0,0 @@
|
|||||||
Short description: Do not define _XOPEN_STREAMS.
|
|
||||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
|
||||||
Origin: PATCH
|
|
||||||
Bug-Fedora: #436349
|
|
||||||
Upstream status: not-submitted
|
|
||||||
|
|
||||||
This patch should go upstream. Not defining _XOPEN_STREAMS is the
|
|
||||||
same as setting it to -1 for POSIX conformance. The headers setting
|
|
||||||
needs to be reviewed indepedently.
|
|
||||||
|
|
||||||
This is part of commit glibc-2.3.3-1564-gd0b6ac6
|
|
||||||
|
|
||||||
* Fri Mar 14 2008 Jakub Jelinek <jakub@redhat.com> 2.7.90-11
|
|
||||||
- remove <stropts.h>, define _XOPEN_STREAMS -1 (#436349)
|
|
||||||
|
|
||||||
diff -Nrup a/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h b/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h
|
|
||||||
--- a/sysdeps/unix/sysv/linux/bits/posix_opt.h 2012-06-05 07:42:49.000000000 -0600
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/bits/posix_opt.h 2012-06-07 12:15:21.817318674 -0600
|
|
||||||
@@ -188,4 +188,7 @@
|
|
||||||
/* Typed memory objects are not available. */
|
|
||||||
#define _POSIX_TYPED_MEMORY_OBJECTS -1
|
|
||||||
|
|
||||||
+/* Streams are not available. */
|
|
||||||
+#define _XOPEN_STREAMS -1
|
|
||||||
+
|
|
||||||
#endif /* bits/posix_opt.h */
|
|
||||||
diff -Nrup a/streams/Makefile b/streams/Makefile
|
|
||||||
--- a/streams/Makefile 2012-06-05 07:42:49.000000000 -0600
|
|
||||||
+++ b/streams/Makefile 2012-06-07 12:15:21.824318649 -0600
|
|
||||||
@@ -20,7 +20,7 @@
|
|
||||||
|
|
||||||
include ../Makeconfig
|
|
||||||
|
|
||||||
-headers = stropts.h sys/stropts.h bits/stropts.h bits/xtitypes.h
|
|
||||||
+#headers = stropts.h sys/stropts.h bits/stropts.h bits/xtitypes.h
|
|
||||||
routines = isastream getmsg getpmsg putmsg putpmsg fattach fdetach
|
|
||||||
|
|
||||||
include ../Rules
|
|
@ -9,32 +9,22 @@ python3 during a transitional phase.
|
|||||||
Author: Carlos O'Donell <carlos@redhat.com>
|
Author: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
diff --git a/benchtests/scripts/compare_bench.py b/benchtests/scripts/compare_bench.py
|
diff --git a/benchtests/scripts/compare_bench.py b/benchtests/scripts/compare_bench.py
|
||||||
index ea25f778c09bba9d..b53beb3c6e32c3cf 100755
|
index 6fcbd0803808e5ca..d43db393d63433bc 100755
|
||||||
--- a/benchtests/scripts/compare_bench.py
|
--- a/benchtests/scripts/compare_bench.py
|
||||||
+++ b/benchtests/scripts/compare_bench.py
|
+++ b/benchtests/scripts/compare_bench.py
|
||||||
@@ -1,4 +1,4 @@
|
@@ -1,4 +1,4 @@
|
||||||
-#!/usr/bin/python
|
-#!/usr/bin/python
|
||||||
+#!/usr/bin/python3
|
+#!/usr/bin/python3
|
||||||
# Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
# Copyright (C) 2015-2021 Free Software Foundation, Inc.
|
||||||
# This file is part of the GNU C Library.
|
# This file is part of the GNU C Library.
|
||||||
#
|
#
|
||||||
diff --git a/benchtests/scripts/import_bench.py b/benchtests/scripts/import_bench.py
|
diff --git a/benchtests/scripts/import_bench.py b/benchtests/scripts/import_bench.py
|
||||||
index 602b3f954d4801a6..76bf1528a5418748 100644
|
index a799b4e1b7dc6f30..3286e267168e83bf 100644
|
||||||
--- a/benchtests/scripts/import_bench.py
|
--- a/benchtests/scripts/import_bench.py
|
||||||
+++ b/benchtests/scripts/import_bench.py
|
+++ b/benchtests/scripts/import_bench.py
|
||||||
@@ -1,4 +1,4 @@
|
@@ -1,4 +1,4 @@
|
||||||
-#!/usr/bin/python
|
-#!/usr/bin/python
|
||||||
+#!/usr/bin/python3
|
+#!/usr/bin/python3
|
||||||
# Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
# Copyright (C) 2015-2021 Free Software Foundation, Inc.
|
||||||
# This file is part of the GNU C Library.
|
|
||||||
#
|
|
||||||
diff --git a/benchtests/scripts/validate_benchout.py b/benchtests/scripts/validate_benchout.py
|
|
||||||
index 6147f05bec3a4844..9a5c7947ee4ed7e9 100755
|
|
||||||
--- a/benchtests/scripts/validate_benchout.py
|
|
||||||
+++ b/benchtests/scripts/validate_benchout.py
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-#!/usr/bin/python
|
|
||||||
+#!/usr/bin/python3
|
|
||||||
# Copyright (C) 2014-2018 Free Software Foundation, Inc.
|
|
||||||
# This file is part of the GNU C Library.
|
# This file is part of the GNU C Library.
|
||||||
#
|
#
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
Backport of this Fedora Rawhide commit but split out into a distinct
|
|
||||||
patch.
|
|
||||||
|
|
||||||
commit 72195d44855ab96875f117acb75c37f98dcb26a9
|
|
||||||
Author: Carlos O'Donell <carlos@redhat.com>
|
|
||||||
Date: Thu Jun 6 23:58:21 2019 -0400
|
|
||||||
|
|
||||||
locale: Fix C.UTF-8 ranges.
|
|
||||||
|
|
||||||
The ellipsis range support only allows <Uxxxx> or <Uxxxxxxxx> as
|
|
||||||
valid unicode code points, otherwise it treats it as a symbol and
|
|
||||||
since we don't define the symbol the entire range is unused.
|
|
||||||
|
|
||||||
diff --git a/localedata/locales/C b/localedata/locales/C
|
|
||||||
index b2c2d1dc417cde69..30d9563213b8cb0f 100644
|
|
||||||
--- a/localedata/locales/C
|
|
||||||
+++ b/localedata/locales/C
|
|
||||||
@@ -43,21 +43,21 @@ order_start forward
|
|
||||||
<U0000>
|
|
||||||
..
|
|
||||||
<UFFFF>
|
|
||||||
-<U10000>
|
|
||||||
+<U00010000>
|
|
||||||
..
|
|
||||||
-<U1FFFF>
|
|
||||||
-<U20000>
|
|
||||||
+<U0001FFFF>
|
|
||||||
+<U00020000>
|
|
||||||
..
|
|
||||||
-<U2FFFF>
|
|
||||||
-<UE0000>
|
|
||||||
+<U0002FFFF>
|
|
||||||
+<U000E0000>
|
|
||||||
..
|
|
||||||
-<UEFFFF>
|
|
||||||
-<UF0000>
|
|
||||||
+<U000EFFFF>
|
|
||||||
+<U000F0000>
|
|
||||||
..
|
|
||||||
-<UFFFFF>
|
|
||||||
-<U100000>
|
|
||||||
+<U000FFFFF>
|
|
||||||
+<U00100000>
|
|
||||||
..
|
|
||||||
-<U10FFFF>
|
|
||||||
+<U0010FFFF>
|
|
||||||
UNDEFINED
|
|
||||||
order_end
|
|
||||||
END LC_COLLATE
|
|
@ -1,185 +0,0 @@
|
|||||||
commit 96cd0558bcd69481ccc42e1b392f0c0b36fce2b0
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Wed Nov 28 19:59:45 2018 +0100
|
|
||||||
|
|
||||||
support: Add signal support to support_capture_subprocess_check
|
|
||||||
|
|
||||||
Signal zero does not terminate a process, so it is safe to use negative
|
|
||||||
values for signal numbers.
|
|
||||||
|
|
||||||
Adjust libio/tst-vtables-common.c to use this new functionality,
|
|
||||||
instead of determining the termination status for a signal indirectly.
|
|
||||||
|
|
||||||
diff --git a/libio/tst-vtables-common.c b/libio/tst-vtables-common.c
|
|
||||||
index 5e3101206919fa1b..85e246cd1131f8e8 100644
|
|
||||||
--- a/libio/tst-vtables-common.c
|
|
||||||
+++ b/libio/tst-vtables-common.c
|
|
||||||
@@ -380,21 +380,6 @@ without_compatibility_fflush (void *closure)
|
|
||||||
_exit (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
-/* Exit status after abnormal termination. */
|
|
||||||
-static int termination_status;
|
|
||||||
-
|
|
||||||
-static void
|
|
||||||
-init_termination_status (void)
|
|
||||||
-{
|
|
||||||
- pid_t pid = xfork ();
|
|
||||||
- if (pid == 0)
|
|
||||||
- abort ();
|
|
||||||
- xwaitpid (pid, &termination_status, 0);
|
|
||||||
-
|
|
||||||
- TEST_VERIFY (WIFSIGNALED (termination_status));
|
|
||||||
- TEST_COMPARE (WTERMSIG (termination_status), SIGABRT);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
static void
|
|
||||||
check_for_termination (const char *name, void (*callback) (void *))
|
|
||||||
{
|
|
||||||
@@ -404,7 +389,7 @@ check_for_termination (const char *name, void (*callback) (void *))
|
|
||||||
shared->calls = 0;
|
|
||||||
struct support_capture_subprocess proc
|
|
||||||
= support_capture_subprocess (callback, NULL);
|
|
||||||
- support_capture_subprocess_check (&proc, name, termination_status,
|
|
||||||
+ support_capture_subprocess_check (&proc, name, -SIGABRT,
|
|
||||||
sc_allow_stderr);
|
|
||||||
const char *message
|
|
||||||
= "Fatal error: glibc detected an invalid stdio handle\n";
|
|
||||||
@@ -491,7 +476,6 @@ run_tests (bool initially_disabled)
|
|
||||||
|
|
||||||
shared = support_shared_allocate (sizeof (*shared));
|
|
||||||
shared->initially_disabled = initially_disabled;
|
|
||||||
- init_termination_status ();
|
|
||||||
|
|
||||||
if (initially_disabled)
|
|
||||||
{
|
|
||||||
diff --git a/support/capture_subprocess.h b/support/capture_subprocess.h
|
|
||||||
index d5eac84d09ae325f..2d2384e73df0d2d0 100644
|
|
||||||
--- a/support/capture_subprocess.h
|
|
||||||
+++ b/support/capture_subprocess.h
|
|
||||||
@@ -55,13 +55,16 @@ enum support_capture_allow
|
|
||||||
sc_allow_stderr = 0x04,
|
|
||||||
};
|
|
||||||
|
|
||||||
-/* Check that the subprocess exited with STATUS and that only the
|
|
||||||
- allowed outputs happened. ALLOWED is a combination of
|
|
||||||
- support_capture_allow flags. Report errors under the CONTEXT
|
|
||||||
- message. */
|
|
||||||
+/* Check that the subprocess exited and that only the allowed outputs
|
|
||||||
+ happened. If STATUS_OR_SIGNAL is nonnegative, it is the expected
|
|
||||||
+ (decoded) exit status of the process, as returned by WEXITSTATUS.
|
|
||||||
+ If STATUS_OR_SIGNAL is negative, -STATUS_OR_SIGNAL is the expected
|
|
||||||
+ termination signal, as returned by WTERMSIG. ALLOWED is a
|
|
||||||
+ combination of support_capture_allow flags. Report errors under
|
|
||||||
+ the CONTEXT message. */
|
|
||||||
void support_capture_subprocess_check (struct support_capture_subprocess *,
|
|
||||||
- const char *context, int status,
|
|
||||||
- int allowed)
|
|
||||||
+ const char *context,
|
|
||||||
+ int status_or_signal, int allowed)
|
|
||||||
__attribute__ ((nonnull (1, 2)));
|
|
||||||
|
|
||||||
#endif /* SUPPORT_CAPTURE_SUBPROCESS_H */
|
|
||||||
diff --git a/support/support_capture_subprocess_check.c b/support/support_capture_subprocess_check.c
|
|
||||||
index ff5ee89fb02599ae..8b4c352c96227b78 100644
|
|
||||||
--- a/support/support_capture_subprocess_check.c
|
|
||||||
+++ b/support/support_capture_subprocess_check.c
|
|
||||||
@@ -20,6 +20,7 @@
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <support/capture_subprocess.h>
|
|
||||||
#include <support/check.h>
|
|
||||||
+#include <sys/wait.h>
|
|
||||||
|
|
||||||
static void
|
|
||||||
print_context (const char *context, bool *failed)
|
|
||||||
@@ -31,9 +32,22 @@ print_context (const char *context, bool *failed)
|
|
||||||
printf ("error: subprocess failed: %s\n", context);
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void
|
|
||||||
+print_actual_status (struct support_capture_subprocess *proc)
|
|
||||||
+{
|
|
||||||
+ if (WIFEXITED (proc->status))
|
|
||||||
+ printf ("error: actual exit status: %d [0x%x]\n",
|
|
||||||
+ WEXITSTATUS (proc->status), proc->status);
|
|
||||||
+ else if (WIFSIGNALED (proc->status))
|
|
||||||
+ printf ("error: actual termination signal: %d [0x%x]\n",
|
|
||||||
+ WTERMSIG (proc->status), proc->status);
|
|
||||||
+ else
|
|
||||||
+ printf ("error: actual undecoded exit status: [0x%x]\n", proc->status);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void
|
|
||||||
support_capture_subprocess_check (struct support_capture_subprocess *proc,
|
|
||||||
- const char *context, int status,
|
|
||||||
+ const char *context, int status_or_signal,
|
|
||||||
int allowed)
|
|
||||||
{
|
|
||||||
TEST_VERIFY ((allowed & sc_allow_none)
|
|
||||||
@@ -44,11 +58,28 @@ support_capture_subprocess_check (struct support_capture_subprocess *proc,
|
|
||||||
|| (allowed & sc_allow_stderr))));
|
|
||||||
|
|
||||||
bool failed = false;
|
|
||||||
- if (proc->status != status)
|
|
||||||
+ if (status_or_signal >= 0)
|
|
||||||
{
|
|
||||||
- print_context (context, &failed);
|
|
||||||
- printf ("error: expected exit status: %d\n", status);
|
|
||||||
- printf ("error: actual exit status: %d\n", proc->status);
|
|
||||||
+ /* Expect regular termination. */
|
|
||||||
+ if (!(WIFEXITED (proc->status)
|
|
||||||
+ && WEXITSTATUS (proc->status) == status_or_signal))
|
|
||||||
+ {
|
|
||||||
+ print_context (context, &failed);
|
|
||||||
+ printf ("error: expected exit status: %d\n", status_or_signal);
|
|
||||||
+ print_actual_status (proc);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ {
|
|
||||||
+ /* status_or_signal < 0. Expect termination by signal. */
|
|
||||||
+ if (!(WIFSIGNALED (proc->status)
|
|
||||||
+ && WTERMSIG (proc->status) == -status_or_signal))
|
|
||||||
+ {
|
|
||||||
+ print_context (context, &failed);
|
|
||||||
+ printf ("error: expected termination signal: %d\n",
|
|
||||||
+ -status_or_signal);
|
|
||||||
+ print_actual_status (proc);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
if (!(allowed & sc_allow_stdout) && proc->out.length != 0)
|
|
||||||
{
|
|
||||||
diff --git a/support/tst-support_capture_subprocess.c b/support/tst-support_capture_subprocess.c
|
|
||||||
index 63b6699622f97fcc..99570879eedd65b1 100644
|
|
||||||
--- a/support/tst-support_capture_subprocess.c
|
|
||||||
+++ b/support/tst-support_capture_subprocess.c
|
|
||||||
@@ -285,15 +285,29 @@ do_multiple_tests (enum test_type type)
|
|
||||||
|
|
||||||
check_stream ("stdout", &result.out, test.out);
|
|
||||||
check_stream ("stderr", &result.err, test.err);
|
|
||||||
+
|
|
||||||
+ /* Allowed output for support_capture_subprocess_check. */
|
|
||||||
+ int check_allow = 0;
|
|
||||||
+ if (lengths[length_idx_stdout] > 0)
|
|
||||||
+ check_allow |= sc_allow_stdout;
|
|
||||||
+ if (lengths[length_idx_stderr] > 0)
|
|
||||||
+ check_allow |= sc_allow_stderr;
|
|
||||||
+ if (check_allow == 0)
|
|
||||||
+ check_allow = sc_allow_none;
|
|
||||||
+
|
|
||||||
if (test.signal != 0)
|
|
||||||
{
|
|
||||||
TEST_VERIFY (WIFSIGNALED (result.status));
|
|
||||||
TEST_VERIFY (WTERMSIG (result.status) == test.signal);
|
|
||||||
+ support_capture_subprocess_check (&result, "signal",
|
|
||||||
+ -SIGTERM, check_allow);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TEST_VERIFY (WIFEXITED (result.status));
|
|
||||||
TEST_VERIFY (WEXITSTATUS (result.status) == test.status);
|
|
||||||
+ support_capture_subprocess_check (&result, "exit",
|
|
||||||
+ test.status, check_allow);
|
|
||||||
}
|
|
||||||
support_capture_subprocess_free (&result);
|
|
||||||
free (test.out);
|
|
@ -1,42 +0,0 @@
|
|||||||
commit e37c2cf299b61ce18f62852f6c5624c27829b610
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Thu Oct 31 18:48:43 2019 +0100
|
|
||||||
|
|
||||||
Move _dl_open_check to its original place in dl_open_worker
|
|
||||||
|
|
||||||
This reverts the non-test change from commit d0093c5cefb7f7a4143f
|
|
||||||
("Call _dl_open_check after relocation [BZ #24259]"), given that
|
|
||||||
the underlying bug has been fixed properly in commit 61b74477fa7f63
|
|
||||||
("Remove all loaded objects if dlopen fails, ignoring NODELETE
|
|
||||||
[BZ #20839]").
|
|
||||||
|
|
||||||
Tested on x86-64-linux-gnu, with and without --enable-cet.
|
|
||||||
|
|
||||||
Change-Id: I995a6cfb89f25d2b0cf5e606428c2a93eb48fc33
|
|
||||||
|
|
||||||
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
|
||||||
index 25838b073ac1edaf..e13968d4d7c4c83f 100644
|
|
||||||
--- a/elf/dl-open.c
|
|
||||||
+++ b/elf/dl-open.c
|
|
||||||
@@ -619,6 +619,8 @@ dl_open_worker (void *a)
|
|
||||||
_dl_debug_state ();
|
|
||||||
LIBC_PROBE (map_complete, 3, args->nsid, r, new);
|
|
||||||
|
|
||||||
+ _dl_open_check (new);
|
|
||||||
+
|
|
||||||
/* Print scope information. */
|
|
||||||
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
|
|
||||||
_dl_show_scope (new, 0);
|
|
||||||
@@ -699,12 +701,6 @@ dl_open_worker (void *a)
|
|
||||||
_dl_relocate_object (l, l->l_scope, reloc_mode, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
- /* NB: Workaround for [BZ #20839] which doesn't remove the NODELETE
|
|
||||||
- object when _dl_open_check throws an exception. Move it after
|
|
||||||
- relocation to avoid leaving the NODELETE object mapped without
|
|
||||||
- relocation. */
|
|
||||||
- _dl_open_check (new);
|
|
||||||
-
|
|
||||||
/* This only performs the memory allocations. The actual update of
|
|
||||||
the scopes happens below, after failure is impossible. */
|
|
||||||
resize_scopes (new);
|
|
@ -1,27 +0,0 @@
|
|||||||
commit 61a7c9df71ee4e6f94b56c20f0d37c6e17d5f284
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Mon Dec 2 14:53:16 2019 +0100
|
|
||||||
|
|
||||||
elf/tst-dlopenfail: Disable --no-as-needed for tst-dlopenfailmod1.so
|
|
||||||
|
|
||||||
Otherwise, the shared object dependency which triggers the load
|
|
||||||
failure is dropped, invalidating the test.
|
|
||||||
|
|
||||||
diff --git a/elf/Makefile b/elf/Makefile
|
|
||||||
index bf7c41f38be42184..467e810e784bb96d 100644
|
|
||||||
--- a/elf/Makefile
|
|
||||||
+++ b/elf/Makefile
|
|
||||||
@@ -1543,8 +1543,11 @@ LDFLAGS-tst-finilazyfailmod.so = \
|
|
||||||
$(objpfx)tst-dlopenfail: $(libdl)
|
|
||||||
$(objpfx)tst-dlopenfail.out: \
|
|
||||||
$(objpfx)tst-dlopenfailmod1.so $(objpfx)tst-dlopenfailmod2.so
|
|
||||||
-# Order matters here. tst-dlopenfaillinkmod.so's soname ensures
|
|
||||||
-# a run-time loader failure.
|
|
||||||
+# Order matters here. tst-dlopenfaillinkmod.so's soname ensures a
|
|
||||||
+# run-time loader failure. --as-needed breaks this test because
|
|
||||||
+# nothing actually references tst-dlopenfailmod2.so (with its soname
|
|
||||||
+# tst-dlopenfail-missingmod.so).
|
|
||||||
+LDFLAGS-tst-dlopenfailmod1.so = -Wl,--no-as-needed
|
|
||||||
$(objpfx)tst-dlopenfailmod1.so: \
|
|
||||||
$(shared-thread-library) $(objpfx)tst-dlopenfaillinkmod.so
|
|
||||||
LDFLAGS-tst-dlopenfaillinkmod.so = -Wl,-soname,tst-dlopenfail-missingmod.so
|
|
File diff suppressed because it is too large
Load Diff
@ -1,328 +0,0 @@
|
|||||||
commit f8ed116aa574435c6e28260f21963233682d3b57
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Fri Dec 13 10:18:46 2019 +0100
|
|
||||||
|
|
||||||
dlopen: Rework handling of pending NODELETE status
|
|
||||||
|
|
||||||
Commit a2e8aa0d9ea648068d8be52dd7b15f1b6a008e23 ("Block signals during
|
|
||||||
the initial part of dlopen") was deemed necessary because of
|
|
||||||
read-modify-write operations like the one in add_dependency in
|
|
||||||
elf/dl-lookup.c. In the old code, we check for any kind of NODELETE
|
|
||||||
status and bail out:
|
|
||||||
|
|
||||||
/* Redo the NODELETE check, as when dl_load_lock wasn't held
|
|
||||||
yet this could have changed. */
|
|
||||||
if (map->l_nodelete != link_map_nodelete_inactive)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
And then set pending status (during relocation):
|
|
||||||
|
|
||||||
if (flags & DL_LOOKUP_FOR_RELOCATE)
|
|
||||||
map->l_nodelete = link_map_nodelete_pending;
|
|
||||||
else
|
|
||||||
map->l_nodelete = link_map_nodelete_active;
|
|
||||||
|
|
||||||
If a signal arrives during relocation and the signal handler, through
|
|
||||||
lazy binding, adds a global scope dependency on the same map, it will
|
|
||||||
set map->l_nodelete to link_map_nodelete_active. This will be
|
|
||||||
overwritten with link_map_nodelete_pending by the dlopen relocation
|
|
||||||
code.
|
|
||||||
|
|
||||||
To avoid such problems in relation to the l_nodelete member, this
|
|
||||||
commit introduces two flags for active NODELETE status (irrevocable)
|
|
||||||
and pending NODELETE status (revocable until activate_nodelete is
|
|
||||||
invoked). As a result, NODELETE processing in dlopen does not
|
|
||||||
introduce further reasons why lazy binding from signal handlers
|
|
||||||
is unsafe during dlopen, and a subsequent commit can remove signal
|
|
||||||
blocking from dlopen.
|
|
||||||
|
|
||||||
This does not address pre-existing issues (unrelated to the NODELETE
|
|
||||||
changes) which make lazy binding in a signal handler during dlopen
|
|
||||||
unsafe, such as the use of malloc in both cases.
|
|
||||||
|
|
||||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
|
||||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
|
||||||
|
|
||||||
diff --git a/elf/dl-close.c b/elf/dl-close.c
|
|
||||||
index 243a028c443173c1..fa7f3e8174576e46 100644
|
|
||||||
--- a/elf/dl-close.c
|
|
||||||
+++ b/elf/dl-close.c
|
|
||||||
@@ -197,7 +197,7 @@ _dl_close_worker (struct link_map *map, bool force)
|
|
||||||
/* Check whether this object is still used. */
|
|
||||||
if (l->l_type == lt_loaded
|
|
||||||
&& l->l_direct_opencount == 0
|
|
||||||
- && l->l_nodelete != link_map_nodelete_active
|
|
||||||
+ && !l->l_nodelete_active
|
|
||||||
/* See CONCURRENCY NOTES in cxa_thread_atexit_impl.c to know why
|
|
||||||
acquire is sufficient and correct. */
|
|
||||||
&& atomic_load_acquire (&l->l_tls_dtor_count) == 0
|
|
||||||
@@ -279,8 +279,7 @@ _dl_close_worker (struct link_map *map, bool force)
|
|
||||||
|
|
||||||
if (!used[i])
|
|
||||||
{
|
|
||||||
- assert (imap->l_type == lt_loaded
|
|
||||||
- && imap->l_nodelete != link_map_nodelete_active);
|
|
||||||
+ assert (imap->l_type == lt_loaded && !imap->l_nodelete_active);
|
|
||||||
|
|
||||||
/* Call its termination function. Do not do it for
|
|
||||||
half-cooked objects. Temporarily disable exception
|
|
||||||
@@ -820,7 +819,7 @@ _dl_close (void *_map)
|
|
||||||
before we took the lock. There is no way to detect this (see below)
|
|
||||||
so we proceed assuming this isn't the case. First see whether we
|
|
||||||
can remove the object at all. */
|
|
||||||
- if (__glibc_unlikely (map->l_nodelete == link_map_nodelete_active))
|
|
||||||
+ if (__glibc_unlikely (map->l_nodelete_active))
|
|
||||||
{
|
|
||||||
/* Nope. Do nothing. */
|
|
||||||
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
|
||||||
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
|
|
||||||
index 35a3f96a6296294a..01724a54f8840f9f 100644
|
|
||||||
--- a/elf/dl-lookup.c
|
|
||||||
+++ b/elf/dl-lookup.c
|
|
||||||
@@ -187,6 +187,28 @@ enter_unique_sym (struct unique_sym *table, size_t size,
|
|
||||||
table[idx].map = map;
|
|
||||||
}
|
|
||||||
|
|
||||||
+/* Mark MAP as NODELETE according to the lookup mode in FLAGS. During
|
|
||||||
+ initial relocation, NODELETE state is pending only. */
|
|
||||||
+static void
|
|
||||||
+mark_nodelete (struct link_map *map, int flags)
|
|
||||||
+{
|
|
||||||
+ if (flags & DL_LOOKUP_FOR_RELOCATE)
|
|
||||||
+ map->l_nodelete_pending = true;
|
|
||||||
+ else
|
|
||||||
+ map->l_nodelete_active = true;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* Return true if MAP is marked as NODELETE according to the lookup
|
|
||||||
+ mode in FLAGS> */
|
|
||||||
+static bool
|
|
||||||
+is_nodelete (struct link_map *map, int flags)
|
|
||||||
+{
|
|
||||||
+ /* Non-pending NODELETE always counts. Pending NODELETE only counts
|
|
||||||
+ during initial relocation processing. */
|
|
||||||
+ return map->l_nodelete_active
|
|
||||||
+ || ((flags & DL_LOOKUP_FOR_RELOCATE) && map->l_nodelete_pending);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/* Utility function for do_lookup_x. Lookup an STB_GNU_UNIQUE symbol
|
|
||||||
in the unique symbol table, creating a new entry if necessary.
|
|
||||||
Return the matching symbol in RESULT. */
|
|
||||||
@@ -311,8 +333,7 @@ do_lookup_unique (const char *undef_name, uint_fast32_t new_hash,
|
|
||||||
enter_unique_sym (entries, size,
|
|
||||||
new_hash, strtab + sym->st_name, sym, map);
|
|
||||||
|
|
||||||
- if (map->l_type == lt_loaded
|
|
||||||
- && map->l_nodelete == link_map_nodelete_inactive)
|
|
||||||
+ if (map->l_type == lt_loaded && !is_nodelete (map, flags))
|
|
||||||
{
|
|
||||||
/* Make sure we don't unload this object by
|
|
||||||
setting the appropriate flag. */
|
|
||||||
@@ -320,10 +341,7 @@ do_lookup_unique (const char *undef_name, uint_fast32_t new_hash,
|
|
||||||
_dl_debug_printf ("\
|
|
||||||
marking %s [%lu] as NODELETE due to unique symbol\n",
|
|
||||||
map->l_name, map->l_ns);
|
|
||||||
- if (flags & DL_LOOKUP_FOR_RELOCATE)
|
|
||||||
- map->l_nodelete = link_map_nodelete_pending;
|
|
||||||
- else
|
|
||||||
- map->l_nodelete = link_map_nodelete_active;
|
|
||||||
+ mark_nodelete (map, flags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
++tab->n_elements;
|
|
||||||
@@ -586,7 +604,7 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
|
|
||||||
dependencies may pick an dependency which can be dlclose'd, but
|
|
||||||
such IFUNC resolvers are undefined anyway. */
|
|
||||||
assert (map->l_type == lt_loaded);
|
|
||||||
- if (map->l_nodelete != link_map_nodelete_inactive)
|
|
||||||
+ if (is_nodelete (map, flags))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
struct link_map_reldeps *l_reldeps
|
|
||||||
@@ -694,17 +712,16 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
|
|
||||||
|
|
||||||
/* Redo the NODELETE check, as when dl_load_lock wasn't held
|
|
||||||
yet this could have changed. */
|
|
||||||
- if (map->l_nodelete != link_map_nodelete_inactive)
|
|
||||||
+ if (is_nodelete (map, flags))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/* If the object with the undefined reference cannot be removed ever
|
|
||||||
just make sure the same is true for the object which contains the
|
|
||||||
definition. */
|
|
||||||
- if (undef_map->l_type != lt_loaded
|
|
||||||
- || (undef_map->l_nodelete != link_map_nodelete_inactive))
|
|
||||||
+ if (undef_map->l_type != lt_loaded || is_nodelete (map, flags))
|
|
||||||
{
|
|
||||||
if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_BINDINGS)
|
|
||||||
- && map->l_nodelete == link_map_nodelete_inactive)
|
|
||||||
+ && !is_nodelete (map, flags))
|
|
||||||
{
|
|
||||||
if (undef_map->l_name[0] == '\0')
|
|
||||||
_dl_debug_printf ("\
|
|
||||||
@@ -716,11 +733,7 @@ marking %s [%lu] as NODELETE due to reference to %s [%lu]\n",
|
|
||||||
map->l_name, map->l_ns,
|
|
||||||
undef_map->l_name, undef_map->l_ns);
|
|
||||||
}
|
|
||||||
-
|
|
||||||
- if (flags & DL_LOOKUP_FOR_RELOCATE)
|
|
||||||
- map->l_nodelete = link_map_nodelete_pending;
|
|
||||||
- else
|
|
||||||
- map->l_nodelete = link_map_nodelete_active;
|
|
||||||
+ mark_nodelete (map, flags);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -746,17 +759,14 @@ marking %s [%lu] as NODELETE due to reference to %s [%lu]\n",
|
|
||||||
cannot be unloaded. This is semantically the correct
|
|
||||||
behavior. */
|
|
||||||
if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_BINDINGS)
|
|
||||||
- && map->l_nodelete == link_map_nodelete_inactive)
|
|
||||||
+ && !is_nodelete (map, flags))
|
|
||||||
_dl_debug_printf ("\
|
|
||||||
marking %s [%lu] as NODELETE due to memory allocation failure\n",
|
|
||||||
map->l_name, map->l_ns);
|
|
||||||
- if (flags & DL_LOOKUP_FOR_RELOCATE)
|
|
||||||
- /* In case of non-lazy binding, we could actually
|
|
||||||
- report the memory allocation error, but for now, we
|
|
||||||
- use the conservative approximation as well. */
|
|
||||||
- map->l_nodelete = link_map_nodelete_pending;
|
|
||||||
- else
|
|
||||||
- map->l_nodelete = link_map_nodelete_active;
|
|
||||||
+ /* In case of non-lazy binding, we could actually report
|
|
||||||
+ the memory allocation error, but for now, we use the
|
|
||||||
+ conservative approximation as well. */
|
|
||||||
+ mark_nodelete (map, flags);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
|
||||||
index c7ed85b7ee99a296..a382bfae8aa3a2f8 100644
|
|
||||||
--- a/elf/dl-open.c
|
|
||||||
+++ b/elf/dl-open.c
|
|
||||||
@@ -440,13 +440,17 @@ activate_nodelete (struct link_map *new)
|
|
||||||
NODELETE status for objects outside the local scope. */
|
|
||||||
for (struct link_map *l = GL (dl_ns)[new->l_ns]._ns_loaded; l != NULL;
|
|
||||||
l = l->l_next)
|
|
||||||
- if (l->l_nodelete == link_map_nodelete_pending)
|
|
||||||
+ if (l->l_nodelete_pending)
|
|
||||||
{
|
|
||||||
if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_FILES))
|
|
||||||
_dl_debug_printf ("activating NODELETE for %s [%lu]\n",
|
|
||||||
l->l_name, l->l_ns);
|
|
||||||
|
|
||||||
- l->l_nodelete = link_map_nodelete_active;
|
|
||||||
+ l->l_nodelete_active = true;
|
|
||||||
+
|
|
||||||
+ /* This is just a debugging aid, to indicate that
|
|
||||||
+ activate_nodelete has run for this map. */
|
|
||||||
+ l->l_nodelete_pending = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -549,10 +553,10 @@ dl_open_worker (void *a)
|
|
||||||
if (__glibc_unlikely (mode & RTLD_NODELETE))
|
|
||||||
{
|
|
||||||
if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_FILES)
|
|
||||||
- && new->l_nodelete == link_map_nodelete_inactive)
|
|
||||||
+ && !new->l_nodelete_active)
|
|
||||||
_dl_debug_printf ("marking %s [%lu] as NODELETE\n",
|
|
||||||
new->l_name, new->l_ns);
|
|
||||||
- new->l_nodelete = link_map_nodelete_active;
|
|
||||||
+ new->l_nodelete_active = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Finalize the addition to the global scope. */
|
|
||||||
@@ -568,7 +572,7 @@ dl_open_worker (void *a)
|
|
||||||
/* Schedule NODELETE marking for the directly loaded object if
|
|
||||||
requested. */
|
|
||||||
if (__glibc_unlikely (mode & RTLD_NODELETE))
|
|
||||||
- new->l_nodelete = link_map_nodelete_pending;
|
|
||||||
+ new->l_nodelete_pending = true;
|
|
||||||
|
|
||||||
/* Load that object's dependencies. */
|
|
||||||
_dl_map_object_deps (new, NULL, 0, 0,
|
|
||||||
@@ -680,7 +684,7 @@ dl_open_worker (void *a)
|
|
||||||
_dl_start_profile ();
|
|
||||||
|
|
||||||
/* Prevent unloading the object. */
|
|
||||||
- GL(dl_profile_map)->l_nodelete = link_map_nodelete_active;
|
|
||||||
+ GL(dl_profile_map)->l_nodelete_active = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
@@ -879,9 +883,9 @@ no more namespaces available for dlmopen()"));
|
|
||||||
happens inside dl_open_worker. */
|
|
||||||
__libc_signal_restore_set (&args.original_signal_mask);
|
|
||||||
|
|
||||||
- /* All link_map_nodelete_pending objects should have been
|
|
||||||
- deleted at this point, which is why it is not necessary
|
|
||||||
- to reset the flag here. */
|
|
||||||
+ /* All l_nodelete_pending objects should have been deleted
|
|
||||||
+ at this point, which is why it is not necessary to reset
|
|
||||||
+ the flag here. */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
__libc_signal_restore_set (&args.original_signal_mask);
|
|
||||||
diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h
|
|
||||||
index ea286abaea0128d1..78ba7e76db9706cc 100644
|
|
||||||
--- a/elf/get-dynamic-info.h
|
|
||||||
+++ b/elf/get-dynamic-info.h
|
|
||||||
@@ -164,7 +164,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
|
|
||||||
{
|
|
||||||
l->l_flags_1 = info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val;
|
|
||||||
if (l->l_flags_1 & DF_1_NODELETE)
|
|
||||||
- l->l_nodelete = link_map_nodelete_pending;
|
|
||||||
+ l->l_nodelete_pending = true;
|
|
||||||
|
|
||||||
/* Only DT_1_SUPPORTED_MASK bits are supported, and we would like
|
|
||||||
to assert this, but we can't. Users have been setting
|
|
||||||
diff --git a/include/link.h b/include/link.h
|
|
||||||
index a277b77cad6b52b1..e90fa79a0b332087 100644
|
|
||||||
--- a/include/link.h
|
|
||||||
+++ b/include/link.h
|
|
||||||
@@ -79,22 +79,6 @@ struct r_search_path_struct
|
|
||||||
int malloced;
|
|
||||||
};
|
|
||||||
|
|
||||||
-/* Type used by the l_nodelete member. */
|
|
||||||
-enum link_map_nodelete
|
|
||||||
-{
|
|
||||||
- /* This link map can be deallocated. */
|
|
||||||
- link_map_nodelete_inactive = 0, /* Zero-initialized in _dl_new_object. */
|
|
||||||
-
|
|
||||||
- /* This link map cannot be deallocated. */
|
|
||||||
- link_map_nodelete_active,
|
|
||||||
-
|
|
||||||
- /* This link map cannot be deallocated after dlopen has succeded.
|
|
||||||
- dlopen turns this into link_map_nodelete_active. dlclose treats
|
|
||||||
- this intermediate state as link_map_nodelete_active. */
|
|
||||||
- link_map_nodelete_pending,
|
|
||||||
-};
|
|
||||||
-
|
|
||||||
-
|
|
||||||
/* Structure describing a loaded shared object. The `l_next' and `l_prev'
|
|
||||||
members form a chain of all the shared objects loaded at startup.
|
|
||||||
|
|
||||||
@@ -218,10 +202,17 @@ struct link_map
|
|
||||||
freed, ie. not allocated with
|
|
||||||
the dummy malloc in ld.so. */
|
|
||||||
|
|
||||||
- /* Actually of type enum link_map_nodelete. Separate byte due to
|
|
||||||
- a read in add_dependency in elf/dl-lookup.c outside the loader
|
|
||||||
- lock. Only valid for l_type == lt_loaded. */
|
|
||||||
- unsigned char l_nodelete;
|
|
||||||
+ /* NODELETE status of the map. Only valid for maps of type
|
|
||||||
+ lt_loaded. Lazy binding sets l_nodelete_active directly,
|
|
||||||
+ potentially from signal handlers. Initial loading of an
|
|
||||||
+ DF_1_NODELETE object set l_nodelete_pending. Relocation may
|
|
||||||
+ set l_nodelete_pending as well. l_nodelete_pending maps are
|
|
||||||
+ promoted to l_nodelete_active status in the final stages of
|
|
||||||
+ dlopen, prior to calling ELF constructors. dlclose only
|
|
||||||
+ refuses to unload l_nodelete_active maps, the pending status is
|
|
||||||
+ ignored. */
|
|
||||||
+ bool l_nodelete_active;
|
|
||||||
+ bool l_nodelete_pending;
|
|
||||||
|
|
||||||
#include <link_map.h>
|
|
||||||
|
|
@ -1,134 +0,0 @@
|
|||||||
commit f7649d5780aa4682393b9daedd653e4d9c12784c
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Fri Dec 13 10:23:10 2019 +0100
|
|
||||||
|
|
||||||
dlopen: Do not block signals
|
|
||||||
|
|
||||||
Blocking signals causes issues with certain anti-malware solutions
|
|
||||||
which rely on an unblocked SIGSYS signal for system calls they
|
|
||||||
intercept.
|
|
||||||
|
|
||||||
This reverts commit a2e8aa0d9ea648068d8be52dd7b15f1b6a008e23
|
|
||||||
("Block signals during the initial part of dlopen") and adds
|
|
||||||
comments related to async signal safety to active_nodelete and
|
|
||||||
its caller.
|
|
||||||
|
|
||||||
Note that this does not make lazy binding async-signal-safe with regards
|
|
||||||
to dlopen. It merely avoids introducing new async-signal-safety hazards
|
|
||||||
as part of the NODELETE changes.
|
|
||||||
|
|
||||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
|
||||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
|
||||||
|
|
||||||
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
|
||||||
index a382bfae8aa3a2f8..d834b89754d2b073 100644
|
|
||||||
--- a/elf/dl-open.c
|
|
||||||
+++ b/elf/dl-open.c
|
|
||||||
@@ -34,7 +34,6 @@
|
|
||||||
#include <atomic.h>
|
|
||||||
#include <libc-internal.h>
|
|
||||||
#include <array_length.h>
|
|
||||||
-#include <internal-signals.h>
|
|
||||||
|
|
||||||
#include <dl-dst.h>
|
|
||||||
#include <dl-prop.h>
|
|
||||||
@@ -53,10 +52,6 @@ struct dl_open_args
|
|
||||||
/* Namespace ID. */
|
|
||||||
Lmid_t nsid;
|
|
||||||
|
|
||||||
- /* Original signal mask. Used for unblocking signal handlers before
|
|
||||||
- running ELF constructors. */
|
|
||||||
- sigset_t original_signal_mask;
|
|
||||||
-
|
|
||||||
/* Original value of _ns_global_scope_pending_adds. Set by
|
|
||||||
dl_open_worker. Only valid if nsid is a real namespace
|
|
||||||
(non-negative). */
|
|
||||||
@@ -446,6 +441,9 @@ activate_nodelete (struct link_map *new)
|
|
||||||
_dl_debug_printf ("activating NODELETE for %s [%lu]\n",
|
|
||||||
l->l_name, l->l_ns);
|
|
||||||
|
|
||||||
+ /* The flag can already be true at this point, e.g. a signal
|
|
||||||
+ handler may have triggered lazy binding and set NODELETE
|
|
||||||
+ status immediately. */
|
|
||||||
l->l_nodelete_active = true;
|
|
||||||
|
|
||||||
/* This is just a debugging aid, to indicate that
|
|
||||||
@@ -520,16 +518,12 @@ dl_open_worker (void *a)
|
|
||||||
if (new == NULL)
|
|
||||||
{
|
|
||||||
assert (mode & RTLD_NOLOAD);
|
|
||||||
- __libc_signal_restore_set (&args->original_signal_mask);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (__glibc_unlikely (mode & __RTLD_SPROF))
|
|
||||||
- {
|
|
||||||
- /* This happens only if we load a DSO for 'sprof'. */
|
|
||||||
- __libc_signal_restore_set (&args->original_signal_mask);
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
+ /* This happens only if we load a DSO for 'sprof'. */
|
|
||||||
+ return;
|
|
||||||
|
|
||||||
/* This object is directly loaded. */
|
|
||||||
++new->l_direct_opencount;
|
|
||||||
@@ -565,7 +559,6 @@ dl_open_worker (void *a)
|
|
||||||
|
|
||||||
assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT);
|
|
||||||
|
|
||||||
- __libc_signal_restore_set (&args->original_signal_mask);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -709,6 +702,12 @@ dl_open_worker (void *a)
|
|
||||||
All memory allocations for new objects must have happened
|
|
||||||
before. */
|
|
||||||
|
|
||||||
+ /* Finalize the NODELETE status first. This comes before
|
|
||||||
+ update_scopes, so that lazy binding will not see pending NODELETE
|
|
||||||
+ state for newly loaded objects. There is a compiler barrier in
|
|
||||||
+ update_scopes which ensures that the changes from
|
|
||||||
+ activate_nodelete are visible before new objects show up in the
|
|
||||||
+ local scope. */
|
|
||||||
activate_nodelete (new);
|
|
||||||
|
|
||||||
/* Second stage after resize_scopes: Actually perform the scope
|
|
||||||
@@ -742,10 +741,6 @@ dl_open_worker (void *a)
|
|
||||||
if (mode & RTLD_GLOBAL)
|
|
||||||
add_to_global_resize (new);
|
|
||||||
|
|
||||||
- /* Unblock signals. Data structures are now consistent, and
|
|
||||||
- application code may run. */
|
|
||||||
- __libc_signal_restore_set (&args->original_signal_mask);
|
|
||||||
-
|
|
||||||
/* Run the initializer functions of new objects. Temporarily
|
|
||||||
disable the exception handler, so that lazy binding failures are
|
|
||||||
fatal. */
|
|
||||||
@@ -835,10 +830,6 @@ no more namespaces available for dlmopen()"));
|
|
||||||
args.argv = argv;
|
|
||||||
args.env = env;
|
|
||||||
|
|
||||||
- /* Recursive lazy binding during manipulation of the dynamic loader
|
|
||||||
- structures may result in incorrect behavior. */
|
|
||||||
- __libc_signal_block_all (&args.original_signal_mask);
|
|
||||||
-
|
|
||||||
struct dl_exception exception;
|
|
||||||
int errcode = _dl_catch_exception (&exception, dl_open_worker, &args);
|
|
||||||
|
|
||||||
@@ -879,16 +870,10 @@ no more namespaces available for dlmopen()"));
|
|
||||||
|
|
||||||
_dl_close_worker (args.map, true);
|
|
||||||
|
|
||||||
- /* Restore the signal mask. In the success case, this
|
|
||||||
- happens inside dl_open_worker. */
|
|
||||||
- __libc_signal_restore_set (&args.original_signal_mask);
|
|
||||||
-
|
|
||||||
/* All l_nodelete_pending objects should have been deleted
|
|
||||||
at this point, which is why it is not necessary to reset
|
|
||||||
the flag here. */
|
|
||||||
}
|
|
||||||
- else
|
|
||||||
- __libc_signal_restore_set (&args.original_signal_mask);
|
|
||||||
|
|
||||||
assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT);
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
|||||||
commit 5177d85b0c050a2333a0c4165c938dd422013d05
|
|
||||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
|
||||||
Date: Thu Jan 16 06:45:36 2020 -0800
|
|
||||||
|
|
||||||
Clear GL(dl_initfirst) when freeing its link_map memory [BZ# 25396]
|
|
||||||
|
|
||||||
We should clear GL(dl_initfirst) when freeing its link_map memory.
|
|
||||||
|
|
||||||
Tested on Fedora 31/x86-64 with CET.
|
|
||||||
|
|
||||||
Reviewed-by: Florian Weimer <fweimer@redhat.com>
|
|
||||||
|
|
||||||
diff --git a/elf/dl-close.c b/elf/dl-close.c
|
|
||||||
index fa7f3e8174576e46..a9ecdff62dba88fb 100644
|
|
||||||
--- a/elf/dl-close.c
|
|
||||||
+++ b/elf/dl-close.c
|
|
||||||
@@ -749,6 +749,10 @@ _dl_close_worker (struct link_map *map, bool force)
|
|
||||||
if (imap->l_runpath_dirs.dirs != (void *) -1)
|
|
||||||
free (imap->l_runpath_dirs.dirs);
|
|
||||||
|
|
||||||
+ /* Clear GL(dl_initfirst) when freeing its link_map memory. */
|
|
||||||
+ if (imap == GL(dl_initfirst))
|
|
||||||
+ GL(dl_initfirst) = NULL;
|
|
||||||
+
|
|
||||||
free (imap);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,143 +0,0 @@
|
|||||||
commit a332bd1518af518c984fad73eba6f46dc5b2b2d4
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Thu Jan 16 16:53:58 2020 +0100
|
|
||||||
|
|
||||||
elf: Add elf/tst-dlopenfail-2 [BZ #25396]
|
|
||||||
|
|
||||||
Without CET, a jump into a newly loaded object through an overwritten
|
|
||||||
link map often does not crash, it just executes some random code.
|
|
||||||
CET detects this in some cases because the function pointer does not
|
|
||||||
point to the start of a function in the replacement shared object,
|
|
||||||
so there is no ENDBR instruction.
|
|
||||||
|
|
||||||
The new test uses a small shared object and the existing dangling
|
|
||||||
link map to trigger the bug.
|
|
||||||
|
|
||||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
|
||||||
|
|
||||||
Conflicts:
|
|
||||||
elf/Makefile
|
|
||||||
(Test backport differences.)
|
|
||||||
|
|
||||||
diff --git a/elf/Makefile b/elf/Makefile
|
|
||||||
index 16a3e8dcda19b4ba..f1a16fe8ca594c57 100644
|
|
||||||
--- a/elf/Makefile
|
|
||||||
+++ b/elf/Makefile
|
|
||||||
@@ -192,7 +192,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
|
|
||||||
tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \
|
|
||||||
tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \
|
|
||||||
tst-sonamemove-link tst-sonamemove-dlopen tst-initfinilazyfail \
|
|
||||||
- tst-dlopenfail
|
|
||||||
+ tst-dlopenfail tst-dlopenfail-2
|
|
||||||
# reldep9
|
|
||||||
tests-internal += loadtest unload unload2 circleload1 \
|
|
||||||
neededtest neededtest2 neededtest3 neededtest4 \
|
|
||||||
@@ -301,7 +301,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
|
||||||
tst-sonamemove-linkmod1 \
|
|
||||||
tst-sonamemove-runmod1 tst-sonamemove-runmod2 \
|
|
||||||
tst-initlazyfailmod tst-finilazyfailmod \
|
|
||||||
- tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2
|
|
||||||
+ tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 \
|
|
||||||
+ tst-dlopenfailmod3
|
|
||||||
|
|
||||||
ifeq (yes,$(have-mtls-dialect-gnu2))
|
|
||||||
tests += tst-gnu2-tls1
|
|
||||||
@@ -1569,6 +1570,10 @@ $(objpfx)tst-dlopenfailmod1.so: \
|
|
||||||
$(shared-thread-library) $(objpfx)tst-dlopenfaillinkmod.so
|
|
||||||
LDFLAGS-tst-dlopenfaillinkmod.so = -Wl,-soname,tst-dlopenfail-missingmod.so
|
|
||||||
$(objpfx)tst-dlopenfailmod2.so: $(shared-thread-library)
|
|
||||||
+$(objpfx)tst-dlopenfail-2: $(libdl)
|
|
||||||
+$(objpfx)tst-dlopenfail.out: \
|
|
||||||
+ $(objpfx)tst-dlopenfailmod1.so $(objpfx)tst-dlopenfailmod2.so \
|
|
||||||
+ $(objpfx)tst-dlopenfailmod3.so
|
|
||||||
|
|
||||||
$(objpfx)tst-dlopen-nodelete-reloc: $(libdl)
|
|
||||||
$(objpfx)tst-dlopen-nodelete-reloc.out: \
|
|
||||||
diff --git a/elf/tst-dlopenfail-2.c b/elf/tst-dlopenfail-2.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000..35bbde64abbb6603
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/elf/tst-dlopenfail-2.c
|
|
||||||
@@ -0,0 +1,59 @@
|
|
||||||
+/* Test unrelated dlopen after dlopen failure involving NODELETE.
|
|
||||||
+ Copyright (C) 2019-2020 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <https://www.gnu.org/licenses/>. */
|
|
||||||
+
|
|
||||||
+#include <dlfcn.h>
|
|
||||||
+#include <errno.h>
|
|
||||||
+#include <gnu/lib-names.h>
|
|
||||||
+#include <stddef.h>
|
|
||||||
+#include <stdio.h>
|
|
||||||
+#include <string.h>
|
|
||||||
+#include <support/check.h>
|
|
||||||
+#include <support/xdlfcn.h>
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+do_test (void)
|
|
||||||
+{
|
|
||||||
+ /* This test uses libpthread as the canonical NODELETE module. If
|
|
||||||
+ libpthread is no longer NODELETE because it has been merged into
|
|
||||||
+ libc, the test needs to be updated. */
|
|
||||||
+ TEST_VERIFY (dlsym (NULL, "pthread_create") == NULL);
|
|
||||||
+
|
|
||||||
+ /* This is expected to fail because of the missing dependency. */
|
|
||||||
+ puts ("info: attempting to load tst-dlopenfailmod1.so");
|
|
||||||
+ TEST_VERIFY (dlopen ("tst-dlopenfailmod1.so", RTLD_LAZY) == NULL);
|
|
||||||
+ const char *message = dlerror ();
|
|
||||||
+ TEST_COMPARE_STRING (message,
|
|
||||||
+ "tst-dlopenfail-missingmod.so:"
|
|
||||||
+ " cannot open shared object file:"
|
|
||||||
+ " No such file or directory");
|
|
||||||
+
|
|
||||||
+ /* Open a small shared object. With a dangling GL (dl_initfirst)
|
|
||||||
+ pointer, this is likely to crash because there is no longer any
|
|
||||||
+ mapped text segment there (bug 25396). */
|
|
||||||
+
|
|
||||||
+ puts ("info: attempting to load tst-dlopenfailmod3.so");
|
|
||||||
+ xdlclose (xdlopen ("tst-dlopenfailmod3.so", RTLD_NOW));
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* Do not perturb the dangling link map. With M_PERTURB, the link map
|
|
||||||
+ appears to have l_init_called set, so there are no constructor
|
|
||||||
+ calls and no crashes. */
|
|
||||||
+#define TEST_NO_MALLOPT
|
|
||||||
+#include <support/test-driver.c>
|
|
||||||
diff --git a/elf/tst-dlopenfailmod3.c b/elf/tst-dlopenfailmod3.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000..636e971264292110
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/elf/tst-dlopenfailmod3.c
|
|
||||||
@@ -0,0 +1,17 @@
|
|
||||||
+/* Empty module for the tst-dlopenfail-2 test.
|
|
||||||
+ Copyright (C) 2020 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <https://www.gnu.org/licenses/>. */
|
|
@ -1,33 +0,0 @@
|
|||||||
commit ca136bb0a36d0a7056c926bfe5126873566efe40
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Thu Oct 31 13:28:26 2019 +0100
|
|
||||||
|
|
||||||
Clarify purpose of assert in _dl_lookup_symbol_x
|
|
||||||
|
|
||||||
Only one of the currently defined flags is incompatible with versioned
|
|
||||||
symbol lookups, so it makes sense to check for that flag and not its
|
|
||||||
complement.
|
|
||||||
|
|
||||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
|
||||||
Reviewed-by: Gabriel F. T. Gomes <gabrielftg@linux.ibm.com>
|
|
||||||
Change-Id: I3384349cef90cfd91862ebc34a4053f0c0a99404
|
|
||||||
|
|
||||||
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
|
|
||||||
index 1d046caf017b582b..efbdb8deb3c0a9d4 100644
|
|
||||||
--- a/elf/dl-lookup.c
|
|
||||||
+++ b/elf/dl-lookup.c
|
|
||||||
@@ -792,11 +792,9 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
|
|
||||||
|
|
||||||
bump_num_relocations ();
|
|
||||||
|
|
||||||
- /* No other flag than DL_LOOKUP_ADD_DEPENDENCY or DL_LOOKUP_GSCOPE_LOCK
|
|
||||||
- is allowed if we look up a versioned symbol. */
|
|
||||||
- assert (version == NULL
|
|
||||||
- || (flags & ~(DL_LOOKUP_ADD_DEPENDENCY | DL_LOOKUP_GSCOPE_LOCK))
|
|
||||||
- == 0);
|
|
||||||
+ /* DL_LOOKUP_RETURN_NEWEST does not make sense for versioned
|
|
||||||
+ lookups. */
|
|
||||||
+ assert (version == NULL || !(flags & DL_LOOKUP_RETURN_NEWEST));
|
|
||||||
|
|
||||||
size_t i = 0;
|
|
||||||
if (__glibc_unlikely (skip_map != NULL))
|
|
@ -1,54 +0,0 @@
|
|||||||
commit 2a764c6ee848dfe92cb2921ed3b14085f15d9e79
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Thu Oct 31 13:23:06 2019 +0100
|
|
||||||
|
|
||||||
Enhance _dl_catch_exception to allow disabling exception handling
|
|
||||||
|
|
||||||
In some cases, it is necessary to introduce noexcept regions
|
|
||||||
where raised dynamic loader exceptions (e.g., from lazy binding)
|
|
||||||
are fatal, despite being nested in a code region with an active
|
|
||||||
exception handler. This change enhances _dl_catch_exception with
|
|
||||||
to provide such a capability. The existing function is reused,
|
|
||||||
so that it is not necessary to introduce yet another function with
|
|
||||||
a similar purpose.
|
|
||||||
|
|
||||||
Change-Id: Iec1bf642ff95a349fdde8040e9baf851ac7b8904
|
|
||||||
|
|
||||||
diff --git a/elf/dl-error-skeleton.c b/elf/dl-error-skeleton.c
|
|
||||||
index d5f418ab1848f0c4..9cb002ccfed2c7b4 100644
|
|
||||||
--- a/elf/dl-error-skeleton.c
|
|
||||||
+++ b/elf/dl-error-skeleton.c
|
|
||||||
@@ -173,6 +173,18 @@ int
|
|
||||||
_dl_catch_exception (struct dl_exception *exception,
|
|
||||||
void (*operate) (void *), void *args)
|
|
||||||
{
|
|
||||||
+ /* If exception is NULL, temporarily disable exception handling.
|
|
||||||
+ Exceptions during operate (args) are fatal. */
|
|
||||||
+ if (exception == NULL)
|
|
||||||
+ {
|
|
||||||
+ struct catch *const old = catch_hook;
|
|
||||||
+ catch_hook = NULL;
|
|
||||||
+ operate (args);
|
|
||||||
+ /* If we get here, the operation was successful. */
|
|
||||||
+ catch_hook = old;
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* We need not handle `receiver' since setting a `catch' is handled
|
|
||||||
before it. */
|
|
||||||
|
|
||||||
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
|
|
||||||
index 95dc87519b80e0ec..cc2484033fe0d902 100644
|
|
||||||
--- a/sysdeps/generic/ldsodefs.h
|
|
||||||
+++ b/sysdeps/generic/ldsodefs.h
|
|
||||||
@@ -852,7 +852,9 @@ libc_hidden_proto (_dl_catch_error)
|
|
||||||
|
|
||||||
/* Call OPERATE (ARGS). If no error occurs, set *EXCEPTION to zero.
|
|
||||||
Otherwise, store a copy of the raised exception in *EXCEPTION,
|
|
||||||
- which has to be freed by _dl_exception_free. */
|
|
||||||
+ which has to be freed by _dl_exception_free. As a special case, if
|
|
||||||
+ EXCEPTION is null, call OPERATE (ARGS) with exception handling
|
|
||||||
+ disabled (so that exceptions are fatal). */
|
|
||||||
int _dl_catch_exception (struct dl_exception *exception,
|
|
||||||
void (*operate) (void *), void *args);
|
|
||||||
libc_hidden_proto (_dl_catch_exception)
|
|
@ -1,42 +0,0 @@
|
|||||||
commit fcb04b9aed26a737159ef7be9c5a6ad0994437dc
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Thu Oct 31 13:28:49 2019 +0100
|
|
||||||
|
|
||||||
Introduce DL_LOOKUP_FOR_RELOCATE flag for _dl_lookup_symbol_x
|
|
||||||
|
|
||||||
This will allow changes in dependency processing during non-lazy
|
|
||||||
binding, for more precise processing of NODELETE objects: During
|
|
||||||
initial relocation in dlopen, the fate of NODELETE objects is still
|
|
||||||
unclear, so objects which are depended upon by NODELETE objects
|
|
||||||
cannot immediately be marked as NODELETE.
|
|
||||||
|
|
||||||
Change-Id: Ic7b94a3f7c4719a00ca8e6018088567824da0658
|
|
||||||
|
|
||||||
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
|
|
||||||
index 053916eeae50467c..afeace4d3e49180c 100644
|
|
||||||
--- a/elf/dl-reloc.c
|
|
||||||
+++ b/elf/dl-reloc.c
|
|
||||||
@@ -248,7 +248,8 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
|
|
||||||
v = (version); \
|
|
||||||
_lr = _dl_lookup_symbol_x (strtab + (*ref)->st_name, l, (ref), \
|
|
||||||
scope, v, _tc, \
|
|
||||||
- DL_LOOKUP_ADD_DEPENDENCY, NULL); \
|
|
||||||
+ DL_LOOKUP_ADD_DEPENDENCY \
|
|
||||||
+ | DL_LOOKUP_FOR_RELOCATE, NULL); \
|
|
||||||
l->l_lookup_cache.ret = (*ref); \
|
|
||||||
l->l_lookup_cache.value = _lr; })) \
|
|
||||||
: l)
|
|
||||||
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
|
|
||||||
index cc2484033fe0d902..6c5298a80bff8e96 100644
|
|
||||||
--- a/sysdeps/generic/ldsodefs.h
|
|
||||||
+++ b/sysdeps/generic/ldsodefs.h
|
|
||||||
@@ -908,6 +908,9 @@ enum
|
|
||||||
DL_LOOKUP_RETURN_NEWEST = 2,
|
|
||||||
/* Set if dl_lookup* called with GSCOPE lock held. */
|
|
||||||
DL_LOOKUP_GSCOPE_LOCK = 4,
|
|
||||||
+ /* Set if dl_lookup is called for non-lazy relocation processing
|
|
||||||
+ from _dl_relocate_object in elf/dl-reloc.c. */
|
|
||||||
+ DL_LOOKUP_FOR_RELOCATE = 8,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Lookup versioned symbol. */
|
|
@ -1,343 +0,0 @@
|
|||||||
commit 79e0cd7b3c997e211fad44a81fd839dc5b2546e8
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Wed Nov 27 16:20:47 2019 +0100
|
|
||||||
|
|
||||||
Lazy binding failures during dlopen/dlclose must be fatal [BZ #24304]
|
|
||||||
|
|
||||||
If a lazy binding failure happens during the execution of an ELF
|
|
||||||
constructor or destructor, the dynamic loader catches the error
|
|
||||||
and reports it using the dlerror mechanism. This is undesirable
|
|
||||||
because there could be other constructors and destructors that
|
|
||||||
need processing (which are skipped), and the process is in an
|
|
||||||
inconsistent state at this point. Therefore, we have to issue
|
|
||||||
a fatal dynamic loader error error and terminate the process.
|
|
||||||
|
|
||||||
Note that the _dl_catch_exception in _dl_open is just an inner catch,
|
|
||||||
to roll back some state locally. If called from dlopen, there is
|
|
||||||
still an outer catch, which is why calling _dl_init via call_dl_init
|
|
||||||
and a no-exception is required and cannot be avoiding by moving the
|
|
||||||
_dl_init call directly into _dl_open.
|
|
||||||
|
|
||||||
_dl_fini does not need changes because it does not install an error
|
|
||||||
handler, so errors are already fatal there.
|
|
||||||
|
|
||||||
Change-Id: I6b1addfe2e30f50a1781595f046f44173db9491a
|
|
||||||
|
|
||||||
Conflicts:
|
|
||||||
elf/Makefile
|
|
||||||
(Usual conflicts due to test backport differences.)
|
|
||||||
|
|
||||||
diff --git a/elf/Makefile b/elf/Makefile
|
|
||||||
index 74a240b3a68ff5e2..b752f6366400d221 100644
|
|
||||||
--- a/elf/Makefile
|
|
||||||
+++ b/elf/Makefile
|
|
||||||
@@ -191,7 +191,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
|
|
||||||
tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \
|
|
||||||
tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \
|
|
||||||
tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \
|
|
||||||
- tst-sonamemove-link tst-sonamemove-dlopen
|
|
||||||
+ tst-sonamemove-link tst-sonamemove-dlopen tst-initfinilazyfail
|
|
||||||
# reldep9
|
|
||||||
tests-internal += loadtest unload unload2 circleload1 \
|
|
||||||
neededtest neededtest2 neededtest3 neededtest4 \
|
|
||||||
@@ -281,7 +281,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
|
||||||
tst-main1mod tst-libc_dlvsym-dso tst-absolute-sym-lib \
|
|
||||||
tst-absolute-zero-lib tst-big-note-lib \
|
|
||||||
tst-sonamemove-linkmod1 \
|
|
||||||
- tst-sonamemove-runmod1 tst-sonamemove-runmod2
|
|
||||||
+ tst-sonamemove-runmod1 tst-sonamemove-runmod2 \
|
|
||||||
+ tst-initlazyfailmod tst-finilazyfailmod
|
|
||||||
|
|
||||||
ifeq (yes,$(have-mtls-dialect-gnu2))
|
|
||||||
tests += tst-gnu2-tls1
|
|
||||||
@@ -1526,3 +1527,13 @@ tst-libc_dlvsym-static-ENV = \
|
|
||||||
$(objpfx)tst-libc_dlvsym-static.out: $(objpfx)tst-libc_dlvsym-dso.so
|
|
||||||
|
|
||||||
$(objpfx)tst-big-note: $(objpfx)tst-big-note-lib.so
|
|
||||||
+
|
|
||||||
+$(objpfx)tst-initfinilazyfail: $(libdl)
|
|
||||||
+$(objpfx)tst-initfinilazyfail.out: \
|
|
||||||
+ $(objpfx)tst-initlazyfailmod.so $(objpfx)tst-finilazyfailmod.so
|
|
||||||
+# Override -z defs, so that we can reference an undefined symbol.
|
|
||||||
+# Force lazy binding for the same reason.
|
|
||||||
+LDFLAGS-tst-initlazyfailmod.so = \
|
|
||||||
+ -Wl,-z,lazy -Wl,--unresolved-symbols=ignore-all
|
|
||||||
+LDFLAGS-tst-finilazyfailmod.so = \
|
|
||||||
+ -Wl,-z,lazy -Wl,--unresolved-symbols=ignore-all
|
|
||||||
diff --git a/elf/dl-close.c b/elf/dl-close.c
|
|
||||||
index ecd6729704ea3294..88aeea25839a34e0 100644
|
|
||||||
--- a/elf/dl-close.c
|
|
||||||
+++ b/elf/dl-close.c
|
|
||||||
@@ -106,6 +106,30 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
+/* Invoke dstructors for CLOSURE (a struct link_map *). Called with
|
|
||||||
+ exception handling temporarily disabled, to make errors fatal. */
|
|
||||||
+static void
|
|
||||||
+call_destructors (void *closure)
|
|
||||||
+{
|
|
||||||
+ struct link_map *map = closure;
|
|
||||||
+
|
|
||||||
+ if (map->l_info[DT_FINI_ARRAY] != NULL)
|
|
||||||
+ {
|
|
||||||
+ ElfW(Addr) *array =
|
|
||||||
+ (ElfW(Addr) *) (map->l_addr
|
|
||||||
+ + map->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
|
|
||||||
+ unsigned int sz = (map->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
|
|
||||||
+ / sizeof (ElfW(Addr)));
|
|
||||||
+
|
|
||||||
+ while (sz-- > 0)
|
|
||||||
+ ((fini_t) array[sz]) ();
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Next try the old-style destructor. */
|
|
||||||
+ if (map->l_info[DT_FINI] != NULL)
|
|
||||||
+ DL_CALL_DT_FINI (map, ((void *) map->l_addr
|
|
||||||
+ + map->l_info[DT_FINI]->d_un.d_ptr));
|
|
||||||
+}
|
|
||||||
|
|
||||||
void
|
|
||||||
_dl_close_worker (struct link_map *map, bool force)
|
|
||||||
@@ -267,7 +291,8 @@ _dl_close_worker (struct link_map *map, bool force)
|
|
||||||
&& (imap->l_flags_1 & DF_1_NODELETE) == 0);
|
|
||||||
|
|
||||||
/* Call its termination function. Do not do it for
|
|
||||||
- half-cooked objects. */
|
|
||||||
+ half-cooked objects. Temporarily disable exception
|
|
||||||
+ handling, so that errors are fatal. */
|
|
||||||
if (imap->l_init_called)
|
|
||||||
{
|
|
||||||
/* When debugging print a message first. */
|
|
||||||
@@ -276,22 +301,9 @@ _dl_close_worker (struct link_map *map, bool force)
|
|
||||||
_dl_debug_printf ("\ncalling fini: %s [%lu]\n\n",
|
|
||||||
imap->l_name, nsid);
|
|
||||||
|
|
||||||
- if (imap->l_info[DT_FINI_ARRAY] != NULL)
|
|
||||||
- {
|
|
||||||
- ElfW(Addr) *array =
|
|
||||||
- (ElfW(Addr) *) (imap->l_addr
|
|
||||||
- + imap->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
|
|
||||||
- unsigned int sz = (imap->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
|
|
||||||
- / sizeof (ElfW(Addr)));
|
|
||||||
-
|
|
||||||
- while (sz-- > 0)
|
|
||||||
- ((fini_t) array[sz]) ();
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- /* Next try the old-style destructor. */
|
|
||||||
- if (imap->l_info[DT_FINI] != NULL)
|
|
||||||
- DL_CALL_DT_FINI (imap, ((void *) imap->l_addr
|
|
||||||
- + imap->l_info[DT_FINI]->d_un.d_ptr));
|
|
||||||
+ if (imap->l_info[DT_FINI_ARRAY] != NULL
|
|
||||||
+ || imap->l_info[DT_FINI] != NULL)
|
|
||||||
+ _dl_catch_exception (NULL, call_destructors, imap);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SHARED
|
|
||||||
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
|
||||||
index 518a6cad699ec6d0..c9c0254ee74c4f4b 100644
|
|
||||||
--- a/elf/dl-open.c
|
|
||||||
+++ b/elf/dl-open.c
|
|
||||||
@@ -177,6 +177,23 @@ _dl_find_dso_for_object (const ElfW(Addr) addr)
|
|
||||||
}
|
|
||||||
rtld_hidden_def (_dl_find_dso_for_object);
|
|
||||||
|
|
||||||
+/* struct dl_init_args and call_dl_init are used to call _dl_init with
|
|
||||||
+ exception handling disabled. */
|
|
||||||
+struct dl_init_args
|
|
||||||
+{
|
|
||||||
+ struct link_map *new;
|
|
||||||
+ int argc;
|
|
||||||
+ char **argv;
|
|
||||||
+ char **env;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+call_dl_init (void *closure)
|
|
||||||
+{
|
|
||||||
+ struct dl_init_args *args = closure;
|
|
||||||
+ _dl_init (args->new, args->argc, args->argv, args->env);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void
|
|
||||||
dl_open_worker (void *a)
|
|
||||||
{
|
|
||||||
@@ -506,8 +523,19 @@ TLS generation counter wrapped! Please report this."));
|
|
||||||
DL_STATIC_INIT (new);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
- /* Run the initializer functions of new objects. */
|
|
||||||
- _dl_init (new, args->argc, args->argv, args->env);
|
|
||||||
+ /* Run the initializer functions of new objects. Temporarily
|
|
||||||
+ disable the exception handler, so that lazy binding failures are
|
|
||||||
+ fatal. */
|
|
||||||
+ {
|
|
||||||
+ struct dl_init_args init_args =
|
|
||||||
+ {
|
|
||||||
+ .new = new,
|
|
||||||
+ .argc = args->argc,
|
|
||||||
+ .argv = args->argv,
|
|
||||||
+ .env = args->env
|
|
||||||
+ };
|
|
||||||
+ _dl_catch_exception (NULL, call_dl_init, &init_args);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
/* Now we can make the new map available in the global scope. */
|
|
||||||
if (mode & RTLD_GLOBAL)
|
|
||||||
diff --git a/elf/tst-finilazyfailmod.c b/elf/tst-finilazyfailmod.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000..2670bd1a9400d0ef
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/elf/tst-finilazyfailmod.c
|
|
||||||
@@ -0,0 +1,27 @@
|
|
||||||
+/* Helper module for tst-initfinilazyfail: lazy binding failure in destructor.
|
|
||||||
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <https://www.gnu.org/licenses/>. */
|
|
||||||
+
|
|
||||||
+/* An undefined function. Calling it will cause a lazy binding
|
|
||||||
+ failure. */
|
|
||||||
+void undefined_function (void);
|
|
||||||
+
|
|
||||||
+static void __attribute__ ((destructor))
|
|
||||||
+fini (void)
|
|
||||||
+{
|
|
||||||
+ undefined_function ();
|
|
||||||
+}
|
|
||||||
diff --git a/elf/tst-initfinilazyfail.c b/elf/tst-initfinilazyfail.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000..9b4a3d0c0ffbb7c6
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/elf/tst-initfinilazyfail.c
|
|
||||||
@@ -0,0 +1,84 @@
|
|
||||||
+/* Test that lazy binding failures in constructors and destructors are fatal.
|
|
||||||
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <https://www.gnu.org/licenses/>. */
|
|
||||||
+
|
|
||||||
+#include <dlfcn.h>
|
|
||||||
+#include <string.h>
|
|
||||||
+#include <support/capture_subprocess.h>
|
|
||||||
+#include <support/check.h>
|
|
||||||
+#include <support/xdlfcn.h>
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+test_constructor (void *closure)
|
|
||||||
+{
|
|
||||||
+ void *handle = dlopen ("tst-initlazyfailmod.so", RTLD_LAZY);
|
|
||||||
+ if (handle == NULL)
|
|
||||||
+ FAIL_EXIT (2, "dlopen did not terminate the process: %s", dlerror ());
|
|
||||||
+ else
|
|
||||||
+ FAIL_EXIT (2, "dlopen did not terminate the process (%p)", handle);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+test_destructor (void *closure)
|
|
||||||
+{
|
|
||||||
+ void *handle = xdlopen ("tst-finilazyfailmod.so", RTLD_LAZY);
|
|
||||||
+ int ret = dlclose (handle);
|
|
||||||
+ const char *message = dlerror ();
|
|
||||||
+ if (message != NULL)
|
|
||||||
+ FAIL_EXIT (2, "dlclose did not terminate the process: %d, %s",
|
|
||||||
+ ret, message);
|
|
||||||
+ else
|
|
||||||
+ FAIL_EXIT (2, "dlopen did not terminate the process: %d", ret);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+do_test (void)
|
|
||||||
+{
|
|
||||||
+ {
|
|
||||||
+ struct support_capture_subprocess proc
|
|
||||||
+ = support_capture_subprocess (test_constructor, NULL);
|
|
||||||
+ support_capture_subprocess_check (&proc, "constructor", 127,
|
|
||||||
+ sc_allow_stderr);
|
|
||||||
+ printf ("info: constructor failure output: [[%s]]\n", proc.err.buffer);
|
|
||||||
+ TEST_VERIFY (strstr (proc.err.buffer,
|
|
||||||
+ "tst-initfinilazyfail: symbol lookup error: ")
|
|
||||||
+ != NULL);
|
|
||||||
+ TEST_VERIFY (strstr (proc.err.buffer,
|
|
||||||
+ "tst-initlazyfailmod.so: undefined symbol:"
|
|
||||||
+ " undefined_function\n") != NULL);
|
|
||||||
+ support_capture_subprocess_free (&proc);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ {
|
|
||||||
+ struct support_capture_subprocess proc
|
|
||||||
+ = support_capture_subprocess (test_destructor, NULL);
|
|
||||||
+ support_capture_subprocess_check (&proc, "destructor", 127,
|
|
||||||
+ sc_allow_stderr);
|
|
||||||
+ printf ("info: destructor failure output: [[%s]]\n", proc.err.buffer);
|
|
||||||
+ TEST_VERIFY (strstr (proc.err.buffer,
|
|
||||||
+ "tst-initfinilazyfail: symbol lookup error: ")
|
|
||||||
+ != NULL);
|
|
||||||
+ TEST_VERIFY (strstr (proc.err.buffer,
|
|
||||||
+ "tst-finilazyfailmod.so: undefined symbol:"
|
|
||||||
+ " undefined_function\n") != NULL);
|
|
||||||
+ support_capture_subprocess_free (&proc);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#include <support/test-driver.c>
|
|
||||||
diff --git a/elf/tst-initlazyfailmod.c b/elf/tst-initlazyfailmod.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000..36348b58d634d2bb
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/elf/tst-initlazyfailmod.c
|
|
||||||
@@ -0,0 +1,27 @@
|
|
||||||
+/* Helper module for tst-initfinilazyfail: lazy binding failure in constructor.
|
|
||||||
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <https://www.gnu.org/licenses/>. */
|
|
||||||
+
|
|
||||||
+/* An undefined function. Calling it will cause a lazy binding
|
|
||||||
+ failure. */
|
|
||||||
+void undefined_function (void);
|
|
||||||
+
|
|
||||||
+static void __attribute__ ((constructor))
|
|
||||||
+init (void)
|
|
||||||
+{
|
|
||||||
+ undefined_function ();
|
|
||||||
+}
|
|
@ -1,308 +0,0 @@
|
|||||||
commit 440b7f8653e4ed8f6e1425145208050b795e9a6c
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Thu Oct 31 18:25:39 2019 +0100
|
|
||||||
|
|
||||||
Avoid late failure in dlopen in global scope update [BZ #25112]
|
|
||||||
|
|
||||||
The call to add_to_global in dl_open_worker happens after running ELF
|
|
||||||
constructors for new objects. At this point, proper recovery from
|
|
||||||
malloc failure would be quite complicated: We would have to run the
|
|
||||||
ELF destructors and close all opened objects, something that we
|
|
||||||
currently do not do.
|
|
||||||
|
|
||||||
Instead, this change splits add_to_global into two phases,
|
|
||||||
add_to_global_resize (which can raise an exception, called before ELF
|
|
||||||
constructors run), and add_to_global_update (which cannot, called
|
|
||||||
after ELF constructors). A complication arises due to recursive
|
|
||||||
dlopen: After the inner dlopen consumes some space, the pre-allocation
|
|
||||||
in the outer dlopen may no longer be sufficient. A new member in the
|
|
||||||
namespace structure, _ns_global_scope_pending_adds keeps track of the
|
|
||||||
maximum number of objects that need to be added to the global scope.
|
|
||||||
This enables the inner add_to_global_resize call to take into account
|
|
||||||
the needs of an outer dlopen.
|
|
||||||
|
|
||||||
Most code in the dynamic linker assumes that the number of global
|
|
||||||
scope entries fits into an unsigned int (matching the r_nlist member
|
|
||||||
of struct r_scop_elem). Therefore, change the type of
|
|
||||||
_ns_global_scope_alloc to unsigned int (from size_t), and add overflow
|
|
||||||
checks.
|
|
||||||
|
|
||||||
Change-Id: Ie08e2f318510d5a6a4bcb1c315f46791b5b77524
|
|
||||||
|
|
||||||
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
|
||||||
index c9c0254ee74c4f4b..85db4f0ecb5f29ce 100644
|
|
||||||
--- a/elf/dl-open.c
|
|
||||||
+++ b/elf/dl-open.c
|
|
||||||
@@ -50,22 +50,38 @@ struct dl_open_args
|
|
||||||
struct link_map *map;
|
|
||||||
/* Namespace ID. */
|
|
||||||
Lmid_t nsid;
|
|
||||||
+
|
|
||||||
+ /* Original value of _ns_global_scope_pending_adds. Set by
|
|
||||||
+ dl_open_worker. Only valid if nsid is a real namespace
|
|
||||||
+ (non-negative). */
|
|
||||||
+ unsigned int original_global_scope_pending_adds;
|
|
||||||
+
|
|
||||||
/* Original parameters to the program and the current environment. */
|
|
||||||
int argc;
|
|
||||||
char **argv;
|
|
||||||
char **env;
|
|
||||||
};
|
|
||||||
|
|
||||||
+/* Called in case the global scope cannot be extended. */
|
|
||||||
+static void __attribute__ ((noreturn))
|
|
||||||
+add_to_global_resize_failure (struct link_map *new)
|
|
||||||
+{
|
|
||||||
+ _dl_signal_error (ENOMEM, new->l_libname->name, NULL,
|
|
||||||
+ N_ ("cannot extend global scope"));
|
|
||||||
+}
|
|
||||||
|
|
||||||
-static int
|
|
||||||
-add_to_global (struct link_map *new)
|
|
||||||
+/* Grow the global scope array for the namespace, so that all the new
|
|
||||||
+ global objects can be added later in add_to_global_update, without
|
|
||||||
+ risk of memory allocation failure. add_to_global_resize raises
|
|
||||||
+ exceptions for memory allocation errors. */
|
|
||||||
+static void
|
|
||||||
+add_to_global_resize (struct link_map *new)
|
|
||||||
{
|
|
||||||
- struct link_map **new_global;
|
|
||||||
- unsigned int to_add = 0;
|
|
||||||
- unsigned int cnt;
|
|
||||||
+ struct link_namespaces *ns = &GL (dl_ns)[new->l_ns];
|
|
||||||
|
|
||||||
/* Count the objects we have to put in the global scope. */
|
|
||||||
- for (cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
|
|
||||||
+ unsigned int to_add = 0;
|
|
||||||
+ for (unsigned int cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
|
|
||||||
if (new->l_searchlist.r_list[cnt]->l_global == 0)
|
|
||||||
++to_add;
|
|
||||||
|
|
||||||
@@ -83,47 +99,51 @@ add_to_global (struct link_map *new)
|
|
||||||
in an realloc() call. Therefore we allocate a completely new
|
|
||||||
array the first time we have to add something to the locale scope. */
|
|
||||||
|
|
||||||
- struct link_namespaces *ns = &GL(dl_ns)[new->l_ns];
|
|
||||||
+ if (__builtin_add_overflow (ns->_ns_global_scope_pending_adds, to_add,
|
|
||||||
+ &ns->_ns_global_scope_pending_adds))
|
|
||||||
+ add_to_global_resize_failure (new);
|
|
||||||
+
|
|
||||||
+ unsigned int new_size = 0; /* 0 means no new allocation. */
|
|
||||||
+ void *old_global = NULL; /* Old allocation if free-able. */
|
|
||||||
+
|
|
||||||
+ /* Minimum required element count for resizing. Adjusted below for
|
|
||||||
+ an exponential resizing policy. */
|
|
||||||
+ size_t required_new_size;
|
|
||||||
+ if (__builtin_add_overflow (ns->_ns_main_searchlist->r_nlist,
|
|
||||||
+ ns->_ns_global_scope_pending_adds,
|
|
||||||
+ &required_new_size))
|
|
||||||
+ add_to_global_resize_failure (new);
|
|
||||||
+
|
|
||||||
if (ns->_ns_global_scope_alloc == 0)
|
|
||||||
{
|
|
||||||
- /* This is the first dynamic object given global scope. */
|
|
||||||
- ns->_ns_global_scope_alloc
|
|
||||||
- = ns->_ns_main_searchlist->r_nlist + to_add + 8;
|
|
||||||
- new_global = (struct link_map **)
|
|
||||||
- malloc (ns->_ns_global_scope_alloc * sizeof (struct link_map *));
|
|
||||||
- if (new_global == NULL)
|
|
||||||
- {
|
|
||||||
- ns->_ns_global_scope_alloc = 0;
|
|
||||||
- nomem:
|
|
||||||
- _dl_signal_error (ENOMEM, new->l_libname->name, NULL,
|
|
||||||
- N_("cannot extend global scope"));
|
|
||||||
- return 1;
|
|
||||||
- }
|
|
||||||
+ if (__builtin_add_overflow (required_new_size, 8, &new_size))
|
|
||||||
+ add_to_global_resize_failure (new);
|
|
||||||
+ }
|
|
||||||
+ else if (required_new_size > ns->_ns_global_scope_alloc)
|
|
||||||
+ {
|
|
||||||
+ if (__builtin_mul_overflow (required_new_size, 2, &new_size))
|
|
||||||
+ add_to_global_resize_failure (new);
|
|
||||||
|
|
||||||
- /* Copy over the old entries. */
|
|
||||||
- ns->_ns_main_searchlist->r_list
|
|
||||||
- = memcpy (new_global, ns->_ns_main_searchlist->r_list,
|
|
||||||
- (ns->_ns_main_searchlist->r_nlist
|
|
||||||
- * sizeof (struct link_map *)));
|
|
||||||
+ /* The old array was allocated with our malloc, not the minimal
|
|
||||||
+ malloc. */
|
|
||||||
+ old_global = ns->_ns_main_searchlist->r_list;
|
|
||||||
}
|
|
||||||
- else if (ns->_ns_main_searchlist->r_nlist + to_add
|
|
||||||
- > ns->_ns_global_scope_alloc)
|
|
||||||
+
|
|
||||||
+ if (new_size > 0)
|
|
||||||
{
|
|
||||||
- /* We have to extend the existing array of link maps in the
|
|
||||||
- main map. */
|
|
||||||
- struct link_map **old_global
|
|
||||||
- = GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list;
|
|
||||||
- size_t new_nalloc = ((ns->_ns_global_scope_alloc + to_add) * 2);
|
|
||||||
-
|
|
||||||
- new_global = (struct link_map **)
|
|
||||||
- malloc (new_nalloc * sizeof (struct link_map *));
|
|
||||||
+ size_t allocation_size;
|
|
||||||
+ if (__builtin_mul_overflow (new_size, sizeof (struct link_map *),
|
|
||||||
+ &allocation_size))
|
|
||||||
+ add_to_global_resize_failure (new);
|
|
||||||
+ struct link_map **new_global = malloc (allocation_size);
|
|
||||||
if (new_global == NULL)
|
|
||||||
- goto nomem;
|
|
||||||
+ add_to_global_resize_failure (new);
|
|
||||||
|
|
||||||
- memcpy (new_global, old_global,
|
|
||||||
- ns->_ns_global_scope_alloc * sizeof (struct link_map *));
|
|
||||||
+ /* Copy over the old entries. */
|
|
||||||
+ memcpy (new_global, ns->_ns_main_searchlist->r_list,
|
|
||||||
+ ns->_ns_main_searchlist->r_nlist * sizeof (struct link_map *));
|
|
||||||
|
|
||||||
- ns->_ns_global_scope_alloc = new_nalloc;
|
|
||||||
+ ns->_ns_global_scope_alloc = new_size;
|
|
||||||
ns->_ns_main_searchlist->r_list = new_global;
|
|
||||||
|
|
||||||
if (!RTLD_SINGLE_THREAD_P)
|
|
||||||
@@ -131,16 +151,28 @@ add_to_global (struct link_map *new)
|
|
||||||
|
|
||||||
free (old_global);
|
|
||||||
}
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* Actually add the new global objects to the global scope. Must be
|
|
||||||
+ called after add_to_global_resize. This function cannot fail. */
|
|
||||||
+static void
|
|
||||||
+add_to_global_update (struct link_map *new)
|
|
||||||
+{
|
|
||||||
+ struct link_namespaces *ns = &GL (dl_ns)[new->l_ns];
|
|
||||||
|
|
||||||
/* Now add the new entries. */
|
|
||||||
unsigned int new_nlist = ns->_ns_main_searchlist->r_nlist;
|
|
||||||
- for (cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
|
|
||||||
+ for (unsigned int cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
|
|
||||||
{
|
|
||||||
struct link_map *map = new->l_searchlist.r_list[cnt];
|
|
||||||
|
|
||||||
if (map->l_global == 0)
|
|
||||||
{
|
|
||||||
map->l_global = 1;
|
|
||||||
+
|
|
||||||
+ /* The array has been resized by add_to_global_resize. */
|
|
||||||
+ assert (new_nlist < ns->_ns_global_scope_alloc);
|
|
||||||
+
|
|
||||||
ns->_ns_main_searchlist->r_list[new_nlist++] = map;
|
|
||||||
|
|
||||||
/* We modify the global scope. Report this. */
|
|
||||||
@@ -149,10 +181,15 @@ add_to_global (struct link_map *new)
|
|
||||||
map->l_name, map->l_ns);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ /* Some of the pending adds have been performed by the loop above.
|
|
||||||
+ Adjust the counter accordingly. */
|
|
||||||
+ unsigned int added = new_nlist - ns->_ns_main_searchlist->r_nlist;
|
|
||||||
+ assert (added <= ns->_ns_global_scope_pending_adds);
|
|
||||||
+ ns->_ns_global_scope_pending_adds -= added;
|
|
||||||
+
|
|
||||||
atomic_write_barrier ();
|
|
||||||
ns->_ns_main_searchlist->r_nlist = new_nlist;
|
|
||||||
-
|
|
||||||
- return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search link maps in all namespaces for the DSO that contains the object at
|
|
||||||
@@ -225,6 +262,10 @@ dl_open_worker (void *a)
|
|
||||||
args->nsid = call_map->l_ns;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* Retain the old value, so that it can be restored. */
|
|
||||||
+ args->original_global_scope_pending_adds
|
|
||||||
+ = GL (dl_ns)[args->nsid]._ns_global_scope_pending_adds;
|
|
||||||
+
|
|
||||||
/* One might be tempted to assert that we are RT_CONSISTENT at this point, but that
|
|
||||||
may not be true if this is a recursive call to dlopen. */
|
|
||||||
_dl_debug_initialize (0, args->nsid);
|
|
||||||
@@ -266,7 +307,10 @@ dl_open_worker (void *a)
|
|
||||||
/* If the user requested the object to be in the global namespace
|
|
||||||
but it is not so far, add it now. */
|
|
||||||
if ((mode & RTLD_GLOBAL) && new->l_global == 0)
|
|
||||||
- (void) add_to_global (new);
|
|
||||||
+ {
|
|
||||||
+ add_to_global_resize (new);
|
|
||||||
+ add_to_global_update (new);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT);
|
|
||||||
|
|
||||||
@@ -523,6 +567,11 @@ TLS generation counter wrapped! Please report this."));
|
|
||||||
DL_STATIC_INIT (new);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+ /* Perform the necessary allocations for adding new global objects
|
|
||||||
+ to the global scope below, via add_to_global_update. */
|
|
||||||
+ if (mode & RTLD_GLOBAL)
|
|
||||||
+ add_to_global_resize (new);
|
|
||||||
+
|
|
||||||
/* Run the initializer functions of new objects. Temporarily
|
|
||||||
disable the exception handler, so that lazy binding failures are
|
|
||||||
fatal. */
|
|
||||||
@@ -539,10 +588,7 @@ TLS generation counter wrapped! Please report this."));
|
|
||||||
|
|
||||||
/* Now we can make the new map available in the global scope. */
|
|
||||||
if (mode & RTLD_GLOBAL)
|
|
||||||
- /* Move the object in the global namespace. */
|
|
||||||
- if (add_to_global (new) != 0)
|
|
||||||
- /* It failed. */
|
|
||||||
- return;
|
|
||||||
+ add_to_global_update (new);
|
|
||||||
|
|
||||||
#ifndef SHARED
|
|
||||||
/* We must be the static _dl_open in libc.a. A static program that
|
|
||||||
@@ -556,7 +602,6 @@ TLS generation counter wrapped! Please report this."));
|
|
||||||
new->l_name, new->l_ns, new->l_direct_opencount);
|
|
||||||
}
|
|
||||||
|
|
||||||
-
|
|
||||||
void *
|
|
||||||
_dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid,
|
|
||||||
int argc, char *argv[], char *env[])
|
|
||||||
@@ -624,6 +669,19 @@ no more namespaces available for dlmopen()"));
|
|
||||||
_dl_unload_cache ();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+ /* Do this for both the error and success cases. The old value has
|
|
||||||
+ only been determined if the namespace ID was assigned (i.e., it
|
|
||||||
+ is not __LM_ID_CALLER). In the success case, we actually may
|
|
||||||
+ have consumed more pending adds than planned (because the local
|
|
||||||
+ scopes overlap in case of a recursive dlopen, the inner dlopen
|
|
||||||
+ doing some of the globalization work of the outer dlopen), so the
|
|
||||||
+ old pending adds value is larger than absolutely necessary.
|
|
||||||
+ Since it is just a conservative upper bound, this is harmless.
|
|
||||||
+ The top-level dlopen call will restore the field to zero. */
|
|
||||||
+ if (args.nsid >= 0)
|
|
||||||
+ GL (dl_ns)[args.nsid]._ns_global_scope_pending_adds
|
|
||||||
+ = args.original_global_scope_pending_adds;
|
|
||||||
+
|
|
||||||
/* See if an error occurred during loading. */
|
|
||||||
if (__glibc_unlikely (exception.errstring != NULL))
|
|
||||||
{
|
|
||||||
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
|
|
||||||
index 6c5298a80bff8e96..57fbefea3cb841e9 100644
|
|
||||||
--- a/sysdeps/generic/ldsodefs.h
|
|
||||||
+++ b/sysdeps/generic/ldsodefs.h
|
|
||||||
@@ -311,7 +311,14 @@ struct rtld_global
|
|
||||||
/* This is zero at program start to signal that the global scope map is
|
|
||||||
allocated by rtld. Later it keeps the size of the map. It might be
|
|
||||||
reset if in _dl_close if the last global object is removed. */
|
|
||||||
- size_t _ns_global_scope_alloc;
|
|
||||||
+ unsigned int _ns_global_scope_alloc;
|
|
||||||
+
|
|
||||||
+ /* During dlopen, this is the number of objects that still need to
|
|
||||||
+ be added to the global scope map. It has to be taken into
|
|
||||||
+ account when resizing the map, for future map additions after
|
|
||||||
+ recursive dlopen calls from ELF constructors. */
|
|
||||||
+ unsigned int _ns_global_scope_pending_adds;
|
|
||||||
+
|
|
||||||
/* Search table for unique objects. */
|
|
||||||
struct unique_sym_table
|
|
||||||
{
|
|
@ -1,490 +0,0 @@
|
|||||||
commit a509eb117fac1d764b15eba64993f4bdb63d7f3c
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Wed Nov 27 16:37:17 2019 +0100
|
|
||||||
|
|
||||||
Avoid late dlopen failure due to scope, TLS slotinfo updates [BZ #25112]
|
|
||||||
|
|
||||||
This change splits the scope and TLS slotinfo updates in dlopen into
|
|
||||||
two parts: one to resize the data structures, and one to actually apply
|
|
||||||
the update. The call to add_to_global_resize in dl_open_worker is moved
|
|
||||||
before the demarcation point at which no further memory allocations are
|
|
||||||
allowed.
|
|
||||||
|
|
||||||
_dl_add_to_slotinfo is adjusted to make the list update optional. There
|
|
||||||
is some optimization possibility here because we could grow the slotinfo
|
|
||||||
list of arrays in a single call, one the largest TLS modid is known.
|
|
||||||
|
|
||||||
This commit does not fix the fatal meory allocation failure in
|
|
||||||
_dl_update_slotinfo. Ideally, this error during dlopen should be
|
|
||||||
recoverable.
|
|
||||||
|
|
||||||
The update order of scopes and TLS data structures is retained, although
|
|
||||||
it appears to be more correct to fully initialize TLS first, and then
|
|
||||||
expose symbols in the newly loaded objects via the scope update.
|
|
||||||
|
|
||||||
Tested on x86_64-linux-gnu.
|
|
||||||
|
|
||||||
Change-Id: I240c58387dabda3ca1bcab48b02115175fa83d6c
|
|
||||||
|
|
||||||
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
|
||||||
index 85db4f0ecb5f29ce..b330cff7d349224a 100644
|
|
||||||
--- a/elf/dl-open.c
|
|
||||||
+++ b/elf/dl-open.c
|
|
||||||
@@ -33,6 +33,7 @@
|
|
||||||
#include <stap-probe.h>
|
|
||||||
#include <atomic.h>
|
|
||||||
#include <libc-internal.h>
|
|
||||||
+#include <array_length.h>
|
|
||||||
|
|
||||||
#include <dl-dst.h>
|
|
||||||
#include <dl-prop.h>
|
|
||||||
@@ -214,6 +215,215 @@ _dl_find_dso_for_object (const ElfW(Addr) addr)
|
|
||||||
}
|
|
||||||
rtld_hidden_def (_dl_find_dso_for_object);
|
|
||||||
|
|
||||||
+/* Return true if NEW is found in the scope for MAP. */
|
|
||||||
+static size_t
|
|
||||||
+scope_has_map (struct link_map *map, struct link_map *new)
|
|
||||||
+{
|
|
||||||
+ size_t cnt;
|
|
||||||
+ for (cnt = 0; map->l_scope[cnt] != NULL; ++cnt)
|
|
||||||
+ if (map->l_scope[cnt] == &new->l_searchlist)
|
|
||||||
+ return true;
|
|
||||||
+ return false;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* Return the length of the scope for MAP. */
|
|
||||||
+static size_t
|
|
||||||
+scope_size (struct link_map *map)
|
|
||||||
+{
|
|
||||||
+ size_t cnt;
|
|
||||||
+ for (cnt = 0; map->l_scope[cnt] != NULL; )
|
|
||||||
+ ++cnt;
|
|
||||||
+ return cnt;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* Resize the scopes of depended-upon objects, so that the new object
|
|
||||||
+ can be added later without further allocation of memory. This
|
|
||||||
+ function can raise an exceptions due to malloc failure. */
|
|
||||||
+static void
|
|
||||||
+resize_scopes (struct link_map *new)
|
|
||||||
+{
|
|
||||||
+ /* If the file is not loaded now as a dependency, add the search
|
|
||||||
+ list of the newly loaded object to the scope. */
|
|
||||||
+ for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
|
|
||||||
+ {
|
|
||||||
+ struct link_map *imap = new->l_searchlist.r_list[i];
|
|
||||||
+
|
|
||||||
+ /* If the initializer has been called already, the object has
|
|
||||||
+ not been loaded here and now. */
|
|
||||||
+ if (imap->l_init_called && imap->l_type == lt_loaded)
|
|
||||||
+ {
|
|
||||||
+ if (scope_has_map (imap, new))
|
|
||||||
+ /* Avoid duplicates. */
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ size_t cnt = scope_size (imap);
|
|
||||||
+ if (__glibc_unlikely (cnt + 1 >= imap->l_scope_max))
|
|
||||||
+ {
|
|
||||||
+ /* The l_scope array is too small. Allocate a new one
|
|
||||||
+ dynamically. */
|
|
||||||
+ size_t new_size;
|
|
||||||
+ struct r_scope_elem **newp;
|
|
||||||
+
|
|
||||||
+ if (imap->l_scope != imap->l_scope_mem
|
|
||||||
+ && imap->l_scope_max < array_length (imap->l_scope_mem))
|
|
||||||
+ {
|
|
||||||
+ /* If the current l_scope memory is not pointing to
|
|
||||||
+ the static memory in the structure, but the
|
|
||||||
+ static memory in the structure is large enough to
|
|
||||||
+ use for cnt + 1 scope entries, then switch to
|
|
||||||
+ using the static memory. */
|
|
||||||
+ new_size = array_length (imap->l_scope_mem);
|
|
||||||
+ newp = imap->l_scope_mem;
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ {
|
|
||||||
+ new_size = imap->l_scope_max * 2;
|
|
||||||
+ newp = (struct r_scope_elem **)
|
|
||||||
+ malloc (new_size * sizeof (struct r_scope_elem *));
|
|
||||||
+ if (newp == NULL)
|
|
||||||
+ _dl_signal_error (ENOMEM, "dlopen", NULL,
|
|
||||||
+ N_("cannot create scope list"));
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Copy the array and the terminating NULL. */
|
|
||||||
+ memcpy (newp, imap->l_scope,
|
|
||||||
+ (cnt + 1) * sizeof (imap->l_scope[0]));
|
|
||||||
+ struct r_scope_elem **old = imap->l_scope;
|
|
||||||
+
|
|
||||||
+ imap->l_scope = newp;
|
|
||||||
+
|
|
||||||
+ if (old != imap->l_scope_mem)
|
|
||||||
+ _dl_scope_free (old);
|
|
||||||
+
|
|
||||||
+ imap->l_scope_max = new_size;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* Second stage of resize_scopes: Add NEW to the scopes. Also print
|
|
||||||
+ debugging information about scopes if requested.
|
|
||||||
+
|
|
||||||
+ This function cannot raise an exception because all required memory
|
|
||||||
+ has been allocated by a previous call to resize_scopes. */
|
|
||||||
+static void
|
|
||||||
+update_scopes (struct link_map *new)
|
|
||||||
+{
|
|
||||||
+ for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
|
|
||||||
+ {
|
|
||||||
+ struct link_map *imap = new->l_searchlist.r_list[i];
|
|
||||||
+ int from_scope = 0;
|
|
||||||
+
|
|
||||||
+ if (imap->l_init_called && imap->l_type == lt_loaded)
|
|
||||||
+ {
|
|
||||||
+ if (scope_has_map (imap, new))
|
|
||||||
+ /* Avoid duplicates. */
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ size_t cnt = scope_size (imap);
|
|
||||||
+ /* Assert that resize_scopes has sufficiently enlarged the
|
|
||||||
+ array. */
|
|
||||||
+ assert (cnt + 1 < imap->l_scope_max);
|
|
||||||
+
|
|
||||||
+ /* First terminate the extended list. Otherwise a thread
|
|
||||||
+ might use the new last element and then use the garbage
|
|
||||||
+ at offset IDX+1. */
|
|
||||||
+ imap->l_scope[cnt + 1] = NULL;
|
|
||||||
+ atomic_write_barrier ();
|
|
||||||
+ imap->l_scope[cnt] = &new->l_searchlist;
|
|
||||||
+
|
|
||||||
+ from_scope = cnt;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Print scope information. */
|
|
||||||
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
|
|
||||||
+ _dl_show_scope (imap, from_scope);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* Call _dl_add_to_slotinfo with DO_ADD set to false, to allocate
|
|
||||||
+ space in GL (dl_tls_dtv_slotinfo_list). This can raise an
|
|
||||||
+ exception. The return value is true if any of the new objects use
|
|
||||||
+ TLS. */
|
|
||||||
+static bool
|
|
||||||
+resize_tls_slotinfo (struct link_map *new)
|
|
||||||
+{
|
|
||||||
+ bool any_tls = false;
|
|
||||||
+ for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
|
|
||||||
+ {
|
|
||||||
+ struct link_map *imap = new->l_searchlist.r_list[i];
|
|
||||||
+
|
|
||||||
+ /* Only add TLS memory if this object is loaded now and
|
|
||||||
+ therefore is not yet initialized. */
|
|
||||||
+ if (! imap->l_init_called && imap->l_tls_blocksize > 0)
|
|
||||||
+ {
|
|
||||||
+ _dl_add_to_slotinfo (imap, false);
|
|
||||||
+ any_tls = true;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ return any_tls;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* Second stage of TLS update, after resize_tls_slotinfo. This
|
|
||||||
+ function does not raise any exception. It should only be called if
|
|
||||||
+ resize_tls_slotinfo returned true. */
|
|
||||||
+static void
|
|
||||||
+update_tls_slotinfo (struct link_map *new)
|
|
||||||
+{
|
|
||||||
+ unsigned int first_static_tls = new->l_searchlist.r_nlist;
|
|
||||||
+ for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
|
|
||||||
+ {
|
|
||||||
+ struct link_map *imap = new->l_searchlist.r_list[i];
|
|
||||||
+
|
|
||||||
+ /* Only add TLS memory if this object is loaded now and
|
|
||||||
+ therefore is not yet initialized. */
|
|
||||||
+ if (! imap->l_init_called && imap->l_tls_blocksize > 0)
|
|
||||||
+ {
|
|
||||||
+ _dl_add_to_slotinfo (imap, true);
|
|
||||||
+
|
|
||||||
+ if (imap->l_need_tls_init
|
|
||||||
+ && first_static_tls == new->l_searchlist.r_nlist)
|
|
||||||
+ first_static_tls = i;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (__builtin_expect (++GL(dl_tls_generation) == 0, 0))
|
|
||||||
+ _dl_fatal_printf (N_("\
|
|
||||||
+TLS generation counter wrapped! Please report this."));
|
|
||||||
+
|
|
||||||
+ /* We need a second pass for static tls data, because
|
|
||||||
+ _dl_update_slotinfo must not be run while calls to
|
|
||||||
+ _dl_add_to_slotinfo are still pending. */
|
|
||||||
+ for (unsigned int i = first_static_tls; i < new->l_searchlist.r_nlist; ++i)
|
|
||||||
+ {
|
|
||||||
+ struct link_map *imap = new->l_searchlist.r_list[i];
|
|
||||||
+
|
|
||||||
+ if (imap->l_need_tls_init
|
|
||||||
+ && ! imap->l_init_called
|
|
||||||
+ && imap->l_tls_blocksize > 0)
|
|
||||||
+ {
|
|
||||||
+ /* For static TLS we have to allocate the memory here and
|
|
||||||
+ now, but we can delay updating the DTV. */
|
|
||||||
+ imap->l_need_tls_init = 0;
|
|
||||||
+#ifdef SHARED
|
|
||||||
+ /* Update the slot information data for at least the
|
|
||||||
+ generation of the DSO we are allocating data for. */
|
|
||||||
+
|
|
||||||
+ /* FIXME: This can terminate the process on memory
|
|
||||||
+ allocation failure. It is not possible to raise
|
|
||||||
+ exceptions from this context; to fix this bug,
|
|
||||||
+ _dl_update_slotinfo would have to be split into two
|
|
||||||
+ operations, similar to resize_scopes and update_scopes
|
|
||||||
+ above. This is related to bug 16134. */
|
|
||||||
+ _dl_update_slotinfo (imap->l_tls_modid);
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+ GL(dl_init_static_tls) (imap);
|
|
||||||
+ assert (imap->l_need_tls_init == 0);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/* struct dl_init_args and call_dl_init are used to call _dl_init with
|
|
||||||
exception handling disabled. */
|
|
||||||
struct dl_init_args
|
|
||||||
@@ -431,133 +641,40 @@ dl_open_worker (void *a)
|
|
||||||
relocation. */
|
|
||||||
_dl_open_check (new);
|
|
||||||
|
|
||||||
- /* If the file is not loaded now as a dependency, add the search
|
|
||||||
- list of the newly loaded object to the scope. */
|
|
||||||
- bool any_tls = false;
|
|
||||||
- unsigned int first_static_tls = new->l_searchlist.r_nlist;
|
|
||||||
- for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
|
|
||||||
- {
|
|
||||||
- struct link_map *imap = new->l_searchlist.r_list[i];
|
|
||||||
- int from_scope = 0;
|
|
||||||
+ /* This only performs the memory allocations. The actual update of
|
|
||||||
+ the scopes happens below, after failure is impossible. */
|
|
||||||
+ resize_scopes (new);
|
|
||||||
|
|
||||||
- /* If the initializer has been called already, the object has
|
|
||||||
- not been loaded here and now. */
|
|
||||||
- if (imap->l_init_called && imap->l_type == lt_loaded)
|
|
||||||
- {
|
|
||||||
- struct r_scope_elem **runp = imap->l_scope;
|
|
||||||
- size_t cnt = 0;
|
|
||||||
-
|
|
||||||
- while (*runp != NULL)
|
|
||||||
- {
|
|
||||||
- if (*runp == &new->l_searchlist)
|
|
||||||
- break;
|
|
||||||
- ++cnt;
|
|
||||||
- ++runp;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- if (*runp != NULL)
|
|
||||||
- /* Avoid duplicates. */
|
|
||||||
- continue;
|
|
||||||
-
|
|
||||||
- if (__glibc_unlikely (cnt + 1 >= imap->l_scope_max))
|
|
||||||
- {
|
|
||||||
- /* The 'r_scope' array is too small. Allocate a new one
|
|
||||||
- dynamically. */
|
|
||||||
- size_t new_size;
|
|
||||||
- struct r_scope_elem **newp;
|
|
||||||
-
|
|
||||||
-#define SCOPE_ELEMS(imap) \
|
|
||||||
- (sizeof (imap->l_scope_mem) / sizeof (imap->l_scope_mem[0]))
|
|
||||||
+ /* Increase the size of the GL (dl_tls_dtv_slotinfo_list) data
|
|
||||||
+ structure. */
|
|
||||||
+ bool any_tls = resize_tls_slotinfo (new);
|
|
||||||
|
|
||||||
- if (imap->l_scope != imap->l_scope_mem
|
|
||||||
- && imap->l_scope_max < SCOPE_ELEMS (imap))
|
|
||||||
- {
|
|
||||||
- new_size = SCOPE_ELEMS (imap);
|
|
||||||
- newp = imap->l_scope_mem;
|
|
||||||
- }
|
|
||||||
- else
|
|
||||||
- {
|
|
||||||
- new_size = imap->l_scope_max * 2;
|
|
||||||
- newp = (struct r_scope_elem **)
|
|
||||||
- malloc (new_size * sizeof (struct r_scope_elem *));
|
|
||||||
- if (newp == NULL)
|
|
||||||
- _dl_signal_error (ENOMEM, "dlopen", NULL,
|
|
||||||
- N_("cannot create scope list"));
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- memcpy (newp, imap->l_scope, cnt * sizeof (imap->l_scope[0]));
|
|
||||||
- struct r_scope_elem **old = imap->l_scope;
|
|
||||||
-
|
|
||||||
- imap->l_scope = newp;
|
|
||||||
-
|
|
||||||
- if (old != imap->l_scope_mem)
|
|
||||||
- _dl_scope_free (old);
|
|
||||||
-
|
|
||||||
- imap->l_scope_max = new_size;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- /* First terminate the extended list. Otherwise a thread
|
|
||||||
- might use the new last element and then use the garbage
|
|
||||||
- at offset IDX+1. */
|
|
||||||
- imap->l_scope[cnt + 1] = NULL;
|
|
||||||
- atomic_write_barrier ();
|
|
||||||
- imap->l_scope[cnt] = &new->l_searchlist;
|
|
||||||
-
|
|
||||||
- /* Print only new scope information. */
|
|
||||||
- from_scope = cnt;
|
|
||||||
- }
|
|
||||||
- /* Only add TLS memory if this object is loaded now and
|
|
||||||
- therefore is not yet initialized. */
|
|
||||||
- else if (! imap->l_init_called
|
|
||||||
- /* Only if the module defines thread local data. */
|
|
||||||
- && __builtin_expect (imap->l_tls_blocksize > 0, 0))
|
|
||||||
- {
|
|
||||||
- /* Now that we know the object is loaded successfully add
|
|
||||||
- modules containing TLS data to the slot info table. We
|
|
||||||
- might have to increase its size. */
|
|
||||||
- _dl_add_to_slotinfo (imap);
|
|
||||||
-
|
|
||||||
- if (imap->l_need_tls_init
|
|
||||||
- && first_static_tls == new->l_searchlist.r_nlist)
|
|
||||||
- first_static_tls = i;
|
|
||||||
-
|
|
||||||
- /* We have to bump the generation counter. */
|
|
||||||
- any_tls = true;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- /* Print scope information. */
|
|
||||||
- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
|
|
||||||
- _dl_show_scope (imap, from_scope);
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- /* Bump the generation number if necessary. */
|
|
||||||
- if (any_tls && __builtin_expect (++GL(dl_tls_generation) == 0, 0))
|
|
||||||
- _dl_fatal_printf (N_("\
|
|
||||||
-TLS generation counter wrapped! Please report this."));
|
|
||||||
-
|
|
||||||
- /* We need a second pass for static tls data, because _dl_update_slotinfo
|
|
||||||
- must not be run while calls to _dl_add_to_slotinfo are still pending. */
|
|
||||||
- for (unsigned int i = first_static_tls; i < new->l_searchlist.r_nlist; ++i)
|
|
||||||
- {
|
|
||||||
- struct link_map *imap = new->l_searchlist.r_list[i];
|
|
||||||
-
|
|
||||||
- if (imap->l_need_tls_init
|
|
||||||
- && ! imap->l_init_called
|
|
||||||
- && imap->l_tls_blocksize > 0)
|
|
||||||
- {
|
|
||||||
- /* For static TLS we have to allocate the memory here and
|
|
||||||
- now, but we can delay updating the DTV. */
|
|
||||||
- imap->l_need_tls_init = 0;
|
|
||||||
-#ifdef SHARED
|
|
||||||
- /* Update the slot information data for at least the
|
|
||||||
- generation of the DSO we are allocating data for. */
|
|
||||||
- _dl_update_slotinfo (imap->l_tls_modid);
|
|
||||||
-#endif
|
|
||||||
+ /* Perform the necessary allocations for adding new global objects
|
|
||||||
+ to the global scope below. */
|
|
||||||
+ if (mode & RTLD_GLOBAL)
|
|
||||||
+ add_to_global_resize (new);
|
|
||||||
|
|
||||||
- GL(dl_init_static_tls) (imap);
|
|
||||||
- assert (imap->l_need_tls_init == 0);
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
+ /* Demarcation point: After this, no recoverable errors are allowed.
|
|
||||||
+ All memory allocations for new objects must have happened
|
|
||||||
+ before. */
|
|
||||||
+
|
|
||||||
+ /* Second stage after resize_scopes: Actually perform the scope
|
|
||||||
+ update. After this, dlsym and lazy binding can bind to new
|
|
||||||
+ objects. */
|
|
||||||
+ update_scopes (new);
|
|
||||||
+
|
|
||||||
+ /* FIXME: It is unclear whether the order here is correct.
|
|
||||||
+ Shouldn't new objects be made available for binding (and thus
|
|
||||||
+ execution) only after there TLS data has been set up fully?
|
|
||||||
+ Fixing bug 16134 will likely make this distinction less
|
|
||||||
+ important. */
|
|
||||||
+
|
|
||||||
+ /* Second stage after resize_tls_slotinfo: Update the slotinfo data
|
|
||||||
+ structures. */
|
|
||||||
+ if (any_tls)
|
|
||||||
+ /* FIXME: This calls _dl_update_slotinfo, which aborts the process
|
|
||||||
+ on memory allocation failure. See bug 16134. */
|
|
||||||
+ update_tls_slotinfo (new);
|
|
||||||
|
|
||||||
/* Notify the debugger all new objects have been relocated. */
|
|
||||||
if (relocation_in_progress)
|
|
||||||
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
|
|
||||||
index c87caf13d6a97ba4..a2def280b7096960 100644
|
|
||||||
--- a/elf/dl-tls.c
|
|
||||||
+++ b/elf/dl-tls.c
|
|
||||||
@@ -883,7 +883,7 @@ _dl_tls_get_addr_soft (struct link_map *l)
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
-_dl_add_to_slotinfo (struct link_map *l)
|
|
||||||
+_dl_add_to_slotinfo (struct link_map *l, bool do_add)
|
|
||||||
{
|
|
||||||
/* Now that we know the object is loaded successfully add
|
|
||||||
modules containing TLS data to the dtv info table. We
|
|
||||||
@@ -939,6 +939,9 @@ cannot create TLS data structures"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add the information into the slotinfo data structure. */
|
|
||||||
- listp->slotinfo[idx].map = l;
|
|
||||||
- listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1;
|
|
||||||
+ if (do_add)
|
|
||||||
+ {
|
|
||||||
+ listp->slotinfo[idx].map = l;
|
|
||||||
+ listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1;
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
diff --git a/elf/rtld.c b/elf/rtld.c
|
|
||||||
index 4ec26a79cbb0aa4f..0aa1a2a19f649e16 100644
|
|
||||||
--- a/elf/rtld.c
|
|
||||||
+++ b/elf/rtld.c
|
|
||||||
@@ -2167,7 +2167,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
|
||||||
|
|
||||||
/* Add object to slot information data if necessasy. */
|
|
||||||
if (l->l_tls_blocksize != 0 && tls_init_tp_called)
|
|
||||||
- _dl_add_to_slotinfo (l);
|
|
||||||
+ _dl_add_to_slotinfo (l, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
@@ -2215,7 +2215,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
|
||||||
|
|
||||||
/* Add object to slot information data if necessasy. */
|
|
||||||
if (l->l_tls_blocksize != 0 && tls_init_tp_called)
|
|
||||||
- _dl_add_to_slotinfo (l);
|
|
||||||
+ _dl_add_to_slotinfo (l, true);
|
|
||||||
}
|
|
||||||
HP_TIMING_NOW (stop);
|
|
||||||
|
|
||||||
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
|
|
||||||
index 57fbefea3cb841e9..c6b7e61badbfd513 100644
|
|
||||||
--- a/sysdeps/generic/ldsodefs.h
|
|
||||||
+++ b/sysdeps/generic/ldsodefs.h
|
|
||||||
@@ -1135,8 +1135,15 @@ extern void *_dl_open (const char *name, int mode, const void *caller,
|
|
||||||
old scope, OLD can't be freed until no thread is using it. */
|
|
||||||
extern int _dl_scope_free (void *) attribute_hidden;
|
|
||||||
|
|
||||||
-/* Add module to slot information data. */
|
|
||||||
-extern void _dl_add_to_slotinfo (struct link_map *l) attribute_hidden;
|
|
||||||
+
|
|
||||||
+/* Add module to slot information data. If DO_ADD is false, only the
|
|
||||||
+ required memory is allocated. Must be called with GL
|
|
||||||
+ (dl_load_lock) acquired. If the function has already been called
|
|
||||||
+ for the link map L with !do_add, then this function will not raise
|
|
||||||
+ an exception, otherwise it is possible that it encounters a memory
|
|
||||||
+ allocation failure. */
|
|
||||||
+extern void _dl_add_to_slotinfo (struct link_map *l, bool do_add)
|
|
||||||
+ attribute_hidden;
|
|
||||||
|
|
||||||
/* Update slot information data for at least the generation of the
|
|
||||||
module with the given index. */
|
|
@ -1,619 +0,0 @@
|
|||||||
commit f63b73814f74032c0e5d0a83300e3d864ef905e5
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Wed Nov 13 15:44:56 2019 +0100
|
|
||||||
|
|
||||||
Remove all loaded objects if dlopen fails, ignoring NODELETE [BZ #20839]
|
|
||||||
|
|
||||||
This introduces a “pending NODELETE” state in the link map, which is
|
|
||||||
flipped to the persistent NODELETE state late in dlopen, via
|
|
||||||
activate_nodelete. During initial relocation, symbol binding
|
|
||||||
records pending NODELETE state only. dlclose ignores pending NODELETE
|
|
||||||
state. Taken together, this results that a partially completed dlopen
|
|
||||||
is rolled back completely because new NODELETE mappings are unloaded.
|
|
||||||
|
|
||||||
Tested on x86_64-linux-gnu and i386-linux-gnu.
|
|
||||||
|
|
||||||
Change-Id: Ib2a3d86af6f92d75baca65431d74783ee0dbc292
|
|
||||||
|
|
||||||
Conflicts:
|
|
||||||
elf/Makefile
|
|
||||||
(Usual conflicts due to test backport differences.)
|
|
||||||
|
|
||||||
diff --git a/elf/Makefile b/elf/Makefile
|
|
||||||
index b752f6366400d221..bf7c41f38be42184 100644
|
|
||||||
--- a/elf/Makefile
|
|
||||||
+++ b/elf/Makefile
|
|
||||||
@@ -191,7 +191,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
|
|
||||||
tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \
|
|
||||||
tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \
|
|
||||||
tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \
|
|
||||||
- tst-sonamemove-link tst-sonamemove-dlopen tst-initfinilazyfail
|
|
||||||
+ tst-sonamemove-link tst-sonamemove-dlopen tst-initfinilazyfail \
|
|
||||||
+ tst-dlopenfail
|
|
||||||
# reldep9
|
|
||||||
tests-internal += loadtest unload unload2 circleload1 \
|
|
||||||
neededtest neededtest2 neededtest3 neededtest4 \
|
|
||||||
@@ -282,7 +283,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
|
||||||
tst-absolute-zero-lib tst-big-note-lib \
|
|
||||||
tst-sonamemove-linkmod1 \
|
|
||||||
tst-sonamemove-runmod1 tst-sonamemove-runmod2 \
|
|
||||||
- tst-initlazyfailmod tst-finilazyfailmod
|
|
||||||
+ tst-initlazyfailmod tst-finilazyfailmod \
|
|
||||||
+ tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2
|
|
||||||
|
|
||||||
ifeq (yes,$(have-mtls-dialect-gnu2))
|
|
||||||
tests += tst-gnu2-tls1
|
|
||||||
@@ -1537,3 +1539,13 @@ LDFLAGS-tst-initlazyfailmod.so = \
|
|
||||||
-Wl,-z,lazy -Wl,--unresolved-symbols=ignore-all
|
|
||||||
LDFLAGS-tst-finilazyfailmod.so = \
|
|
||||||
-Wl,-z,lazy -Wl,--unresolved-symbols=ignore-all
|
|
||||||
+
|
|
||||||
+$(objpfx)tst-dlopenfail: $(libdl)
|
|
||||||
+$(objpfx)tst-dlopenfail.out: \
|
|
||||||
+ $(objpfx)tst-dlopenfailmod1.so $(objpfx)tst-dlopenfailmod2.so
|
|
||||||
+# Order matters here. tst-dlopenfaillinkmod.so's soname ensures
|
|
||||||
+# a run-time loader failure.
|
|
||||||
+$(objpfx)tst-dlopenfailmod1.so: \
|
|
||||||
+ $(shared-thread-library) $(objpfx)tst-dlopenfaillinkmod.so
|
|
||||||
+LDFLAGS-tst-dlopenfaillinkmod.so = -Wl,-soname,tst-dlopenfail-missingmod.so
|
|
||||||
+$(objpfx)tst-dlopenfailmod2.so: $(shared-thread-library)
|
|
||||||
diff --git a/elf/dl-close.c b/elf/dl-close.c
|
|
||||||
index 88aeea25839a34e0..243a028c443173c1 100644
|
|
||||||
--- a/elf/dl-close.c
|
|
||||||
+++ b/elf/dl-close.c
|
|
||||||
@@ -168,14 +168,6 @@ _dl_close_worker (struct link_map *map, bool force)
|
|
||||||
char done[nloaded];
|
|
||||||
struct link_map *maps[nloaded];
|
|
||||||
|
|
||||||
- /* Clear DF_1_NODELETE to force object deletion. We don't need to touch
|
|
||||||
- l_tls_dtor_count because forced object deletion only happens when an
|
|
||||||
- error occurs during object load. Destructor registration for TLS
|
|
||||||
- non-POD objects should not have happened till then for this
|
|
||||||
- object. */
|
|
||||||
- if (force)
|
|
||||||
- map->l_flags_1 &= ~DF_1_NODELETE;
|
|
||||||
-
|
|
||||||
/* Run over the list and assign indexes to the link maps and enter
|
|
||||||
them into the MAPS array. */
|
|
||||||
int idx = 0;
|
|
||||||
@@ -205,7 +197,7 @@ _dl_close_worker (struct link_map *map, bool force)
|
|
||||||
/* Check whether this object is still used. */
|
|
||||||
if (l->l_type == lt_loaded
|
|
||||||
&& l->l_direct_opencount == 0
|
|
||||||
- && (l->l_flags_1 & DF_1_NODELETE) == 0
|
|
||||||
+ && l->l_nodelete != link_map_nodelete_active
|
|
||||||
/* See CONCURRENCY NOTES in cxa_thread_atexit_impl.c to know why
|
|
||||||
acquire is sufficient and correct. */
|
|
||||||
&& atomic_load_acquire (&l->l_tls_dtor_count) == 0
|
|
||||||
@@ -288,7 +280,7 @@ _dl_close_worker (struct link_map *map, bool force)
|
|
||||||
if (!used[i])
|
|
||||||
{
|
|
||||||
assert (imap->l_type == lt_loaded
|
|
||||||
- && (imap->l_flags_1 & DF_1_NODELETE) == 0);
|
|
||||||
+ && imap->l_nodelete != link_map_nodelete_active);
|
|
||||||
|
|
||||||
/* Call its termination function. Do not do it for
|
|
||||||
half-cooked objects. Temporarily disable exception
|
|
||||||
@@ -828,7 +820,7 @@ _dl_close (void *_map)
|
|
||||||
before we took the lock. There is no way to detect this (see below)
|
|
||||||
so we proceed assuming this isn't the case. First see whether we
|
|
||||||
can remove the object at all. */
|
|
||||||
- if (__glibc_unlikely (map->l_flags_1 & DF_1_NODELETE))
|
|
||||||
+ if (__glibc_unlikely (map->l_nodelete == link_map_nodelete_active))
|
|
||||||
{
|
|
||||||
/* Nope. Do nothing. */
|
|
||||||
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
|
||||||
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
|
|
||||||
index efbdb8deb3c0a9d4..c5e5857fb1fe2808 100644
|
|
||||||
--- a/elf/dl-lookup.c
|
|
||||||
+++ b/elf/dl-lookup.c
|
|
||||||
@@ -192,9 +192,10 @@ enter_unique_sym (struct unique_sym *table, size_t size,
|
|
||||||
Return the matching symbol in RESULT. */
|
|
||||||
static void
|
|
||||||
do_lookup_unique (const char *undef_name, uint_fast32_t new_hash,
|
|
||||||
- const struct link_map *map, struct sym_val *result,
|
|
||||||
+ struct link_map *map, struct sym_val *result,
|
|
||||||
int type_class, const ElfW(Sym) *sym, const char *strtab,
|
|
||||||
- const ElfW(Sym) *ref, const struct link_map *undef_map)
|
|
||||||
+ const ElfW(Sym) *ref, const struct link_map *undef_map,
|
|
||||||
+ int flags)
|
|
||||||
{
|
|
||||||
/* We have to determine whether we already found a symbol with this
|
|
||||||
name before. If not then we have to add it to the search table.
|
|
||||||
@@ -222,7 +223,7 @@ do_lookup_unique (const char *undef_name, uint_fast32_t new_hash,
|
|
||||||
copy from the copy addressed through the
|
|
||||||
relocation. */
|
|
||||||
result->s = sym;
|
|
||||||
- result->m = (struct link_map *) map;
|
|
||||||
+ result->m = map;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
@@ -311,9 +312,19 @@ do_lookup_unique (const char *undef_name, uint_fast32_t new_hash,
|
|
||||||
new_hash, strtab + sym->st_name, sym, map);
|
|
||||||
|
|
||||||
if (map->l_type == lt_loaded)
|
|
||||||
- /* Make sure we don't unload this object by
|
|
||||||
- setting the appropriate flag. */
|
|
||||||
- ((struct link_map *) map)->l_flags_1 |= DF_1_NODELETE;
|
|
||||||
+ {
|
|
||||||
+ /* Make sure we don't unload this object by
|
|
||||||
+ setting the appropriate flag. */
|
|
||||||
+ if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_BINDINGS)
|
|
||||||
+ && map->l_nodelete == link_map_nodelete_inactive)
|
|
||||||
+ _dl_debug_printf ("\
|
|
||||||
+marking %s [%lu] as NODELETE due to unique symbol\n",
|
|
||||||
+ map->l_name, map->l_ns);
|
|
||||||
+ if (flags & DL_LOOKUP_FOR_RELOCATE)
|
|
||||||
+ map->l_nodelete = link_map_nodelete_pending;
|
|
||||||
+ else
|
|
||||||
+ map->l_nodelete = link_map_nodelete_active;
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
++tab->n_elements;
|
|
||||||
|
|
||||||
@@ -525,8 +536,9 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
case STB_GNU_UNIQUE:;
|
|
||||||
- do_lookup_unique (undef_name, new_hash, map, result, type_class,
|
|
||||||
- sym, strtab, ref, undef_map);
|
|
||||||
+ do_lookup_unique (undef_name, new_hash, (struct link_map *) map,
|
|
||||||
+ result, type_class, sym, strtab, ref,
|
|
||||||
+ undef_map, flags);
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
default:
|
|
||||||
@@ -568,9 +580,13 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
|
|
||||||
if (undef_map == map)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
- /* Avoid references to objects which cannot be unloaded anyway. */
|
|
||||||
+ /* Avoid references to objects which cannot be unloaded anyway. We
|
|
||||||
+ do not need to record dependencies if this object goes away
|
|
||||||
+ during dlopen failure, either. IFUNC resolvers with relocation
|
|
||||||
+ dependencies may pick an dependency which can be dlclose'd, but
|
|
||||||
+ such IFUNC resolvers are undefined anyway. */
|
|
||||||
assert (map->l_type == lt_loaded);
|
|
||||||
- if ((map->l_flags_1 & DF_1_NODELETE) != 0)
|
|
||||||
+ if (map->l_nodelete != link_map_nodelete_inactive)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
struct link_map_reldeps *l_reldeps
|
|
||||||
@@ -678,16 +694,33 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
|
|
||||||
|
|
||||||
/* Redo the NODELETE check, as when dl_load_lock wasn't held
|
|
||||||
yet this could have changed. */
|
|
||||||
- if ((map->l_flags_1 & DF_1_NODELETE) != 0)
|
|
||||||
+ if (map->l_nodelete != link_map_nodelete_inactive)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/* If the object with the undefined reference cannot be removed ever
|
|
||||||
just make sure the same is true for the object which contains the
|
|
||||||
definition. */
|
|
||||||
if (undef_map->l_type != lt_loaded
|
|
||||||
- || (undef_map->l_flags_1 & DF_1_NODELETE) != 0)
|
|
||||||
+ || (undef_map->l_nodelete != link_map_nodelete_inactive))
|
|
||||||
{
|
|
||||||
- map->l_flags_1 |= DF_1_NODELETE;
|
|
||||||
+ if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_BINDINGS)
|
|
||||||
+ && map->l_nodelete == link_map_nodelete_inactive)
|
|
||||||
+ {
|
|
||||||
+ if (undef_map->l_name[0] == '\0')
|
|
||||||
+ _dl_debug_printf ("\
|
|
||||||
+marking %s [%lu] as NODELETE due to reference to main program\n",
|
|
||||||
+ map->l_name, map->l_ns);
|
|
||||||
+ else
|
|
||||||
+ _dl_debug_printf ("\
|
|
||||||
+marking %s [%lu] as NODELETE due to reference to %s [%lu]\n",
|
|
||||||
+ map->l_name, map->l_ns,
|
|
||||||
+ undef_map->l_name, undef_map->l_ns);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (flags & DL_LOOKUP_FOR_RELOCATE)
|
|
||||||
+ map->l_nodelete = link_map_nodelete_pending;
|
|
||||||
+ else
|
|
||||||
+ map->l_nodelete = link_map_nodelete_active;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -712,7 +745,18 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
|
|
||||||
no fatal problem. We simply make sure the referenced object
|
|
||||||
cannot be unloaded. This is semantically the correct
|
|
||||||
behavior. */
|
|
||||||
- map->l_flags_1 |= DF_1_NODELETE;
|
|
||||||
+ if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_BINDINGS)
|
|
||||||
+ && map->l_nodelete == link_map_nodelete_inactive)
|
|
||||||
+ _dl_debug_printf ("\
|
|
||||||
+marking %s [%lu] as NODELETE due to memory allocation failure\n",
|
|
||||||
+ map->l_name, map->l_ns);
|
|
||||||
+ if (flags & DL_LOOKUP_FOR_RELOCATE)
|
|
||||||
+ /* In case of non-lazy binding, we could actually
|
|
||||||
+ report the memory allocation error, but for now, we
|
|
||||||
+ use the conservative approximation as well. */
|
|
||||||
+ map->l_nodelete = link_map_nodelete_pending;
|
|
||||||
+ else
|
|
||||||
+ map->l_nodelete = link_map_nodelete_active;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
|
||||||
index b330cff7d349224a..79c6e4c8ed1c9dfa 100644
|
|
||||||
--- a/elf/dl-open.c
|
|
||||||
+++ b/elf/dl-open.c
|
|
||||||
@@ -424,6 +424,40 @@ TLS generation counter wrapped! Please report this."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+/* Mark the objects as NODELETE if required. This is delayed until
|
|
||||||
+ after dlopen failure is not possible, so that _dl_close can clean
|
|
||||||
+ up objects if necessary. */
|
|
||||||
+static void
|
|
||||||
+activate_nodelete (struct link_map *new, int mode)
|
|
||||||
+{
|
|
||||||
+ if (mode & RTLD_NODELETE || new->l_nodelete == link_map_nodelete_pending)
|
|
||||||
+ {
|
|
||||||
+ if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_FILES))
|
|
||||||
+ _dl_debug_printf ("activating NODELETE for %s [%lu]\n",
|
|
||||||
+ new->l_name, new->l_ns);
|
|
||||||
+ new->l_nodelete = link_map_nodelete_active;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
|
|
||||||
+ {
|
|
||||||
+ struct link_map *imap = new->l_searchlist.r_list[i];
|
|
||||||
+ if (imap->l_nodelete == link_map_nodelete_pending)
|
|
||||||
+ {
|
|
||||||
+ if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_FILES))
|
|
||||||
+ _dl_debug_printf ("activating NODELETE for %s [%lu]\n",
|
|
||||||
+ imap->l_name, imap->l_ns);
|
|
||||||
+
|
|
||||||
+ /* Only new objects should have set
|
|
||||||
+ link_map_nodelete_pending. Existing objects should not
|
|
||||||
+ have gained any new dependencies and therefore cannot
|
|
||||||
+ reach NODELETE status. */
|
|
||||||
+ assert (!imap->l_init_called || imap->l_type != lt_loaded);
|
|
||||||
+
|
|
||||||
+ imap->l_nodelete = link_map_nodelete_active;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/* struct dl_init_args and call_dl_init are used to call _dl_init with
|
|
||||||
exception handling disabled. */
|
|
||||||
struct dl_init_args
|
|
||||||
@@ -493,12 +527,6 @@ dl_open_worker (void *a)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
- /* Mark the object as not deletable if the RTLD_NODELETE flags was passed.
|
|
||||||
- Do this early so that we don't skip marking the object if it was
|
|
||||||
- already loaded. */
|
|
||||||
- if (__glibc_unlikely (mode & RTLD_NODELETE))
|
|
||||||
- new->l_flags_1 |= DF_1_NODELETE;
|
|
||||||
-
|
|
||||||
if (__glibc_unlikely (mode & __RTLD_SPROF))
|
|
||||||
/* This happens only if we load a DSO for 'sprof'. */
|
|
||||||
return;
|
|
||||||
@@ -514,19 +542,37 @@ dl_open_worker (void *a)
|
|
||||||
_dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n",
|
|
||||||
new->l_name, new->l_ns, new->l_direct_opencount);
|
|
||||||
|
|
||||||
- /* If the user requested the object to be in the global namespace
|
|
||||||
- but it is not so far, add it now. */
|
|
||||||
+ /* If the user requested the object to be in the global
|
|
||||||
+ namespace but it is not so far, prepare to add it now. This
|
|
||||||
+ can raise an exception to do a malloc failure. */
|
|
||||||
if ((mode & RTLD_GLOBAL) && new->l_global == 0)
|
|
||||||
+ add_to_global_resize (new);
|
|
||||||
+
|
|
||||||
+ /* Mark the object as not deletable if the RTLD_NODELETE flags
|
|
||||||
+ was passed. */
|
|
||||||
+ if (__glibc_unlikely (mode & RTLD_NODELETE))
|
|
||||||
{
|
|
||||||
- add_to_global_resize (new);
|
|
||||||
- add_to_global_update (new);
|
|
||||||
+ if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_FILES)
|
|
||||||
+ && new->l_nodelete == link_map_nodelete_inactive)
|
|
||||||
+ _dl_debug_printf ("marking %s [%lu] as NODELETE\n",
|
|
||||||
+ new->l_name, new->l_ns);
|
|
||||||
+ new->l_nodelete = link_map_nodelete_active;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* Finalize the addition to the global scope. */
|
|
||||||
+ if ((mode & RTLD_GLOBAL) && new->l_global == 0)
|
|
||||||
+ add_to_global_update (new);
|
|
||||||
+
|
|
||||||
assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* Schedule NODELETE marking for the directly loaded object if
|
|
||||||
+ requested. */
|
|
||||||
+ if (__glibc_unlikely (mode & RTLD_NODELETE))
|
|
||||||
+ new->l_nodelete = link_map_nodelete_pending;
|
|
||||||
+
|
|
||||||
/* Load that object's dependencies. */
|
|
||||||
_dl_map_object_deps (new, NULL, 0, 0,
|
|
||||||
mode & (__RTLD_DLOPEN | RTLD_DEEPBIND | __RTLD_AUDIT));
|
|
||||||
@@ -598,6 +644,14 @@ dl_open_worker (void *a)
|
|
||||||
|
|
||||||
int relocation_in_progress = 0;
|
|
||||||
|
|
||||||
+ /* Perform relocation. This can trigger lazy binding in IFUNC
|
|
||||||
+ resolvers. For NODELETE mappings, these dependencies are not
|
|
||||||
+ recorded because the flag has not been applied to the newly
|
|
||||||
+ loaded objects. This means that upon dlopen failure, these
|
|
||||||
+ NODELETE objects can be unloaded despite existing references to
|
|
||||||
+ them. However, such relocation dependencies in IFUNC resolvers
|
|
||||||
+ are undefined anyway, so this is not a problem. */
|
|
||||||
+
|
|
||||||
for (unsigned int i = nmaps; i-- > 0; )
|
|
||||||
{
|
|
||||||
l = maps[i];
|
|
||||||
@@ -627,7 +681,7 @@ dl_open_worker (void *a)
|
|
||||||
_dl_start_profile ();
|
|
||||||
|
|
||||||
/* Prevent unloading the object. */
|
|
||||||
- GL(dl_profile_map)->l_flags_1 |= DF_1_NODELETE;
|
|
||||||
+ GL(dl_profile_map)->l_nodelete = link_map_nodelete_active;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
@@ -658,6 +712,8 @@ dl_open_worker (void *a)
|
|
||||||
All memory allocations for new objects must have happened
|
|
||||||
before. */
|
|
||||||
|
|
||||||
+ activate_nodelete (new, mode);
|
|
||||||
+
|
|
||||||
/* Second stage after resize_scopes: Actually perform the scope
|
|
||||||
update. After this, dlsym and lazy binding can bind to new
|
|
||||||
objects. */
|
|
||||||
@@ -817,6 +873,10 @@ no more namespaces available for dlmopen()"));
|
|
||||||
GL(dl_tls_dtv_gaps) = true;
|
|
||||||
|
|
||||||
_dl_close_worker (args.map, true);
|
|
||||||
+
|
|
||||||
+ /* All link_map_nodelete_pending objects should have been
|
|
||||||
+ deleted at this point, which is why it is not necessary
|
|
||||||
+ to reset the flag here. */
|
|
||||||
}
|
|
||||||
|
|
||||||
assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT);
|
|
||||||
diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h
|
|
||||||
index 4b1ea7c4078ee947..ea286abaea0128d1 100644
|
|
||||||
--- a/elf/get-dynamic-info.h
|
|
||||||
+++ b/elf/get-dynamic-info.h
|
|
||||||
@@ -163,6 +163,8 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
|
|
||||||
if (info[VERSYMIDX (DT_FLAGS_1)] != NULL)
|
|
||||||
{
|
|
||||||
l->l_flags_1 = info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val;
|
|
||||||
+ if (l->l_flags_1 & DF_1_NODELETE)
|
|
||||||
+ l->l_nodelete = link_map_nodelete_pending;
|
|
||||||
|
|
||||||
/* Only DT_1_SUPPORTED_MASK bits are supported, and we would like
|
|
||||||
to assert this, but we can't. Users have been setting
|
|
||||||
diff --git a/elf/tst-dlopenfail.c b/elf/tst-dlopenfail.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000..ce3140c899562ca8
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/elf/tst-dlopenfail.c
|
|
||||||
@@ -0,0 +1,79 @@
|
|
||||||
+/* Test dlopen rollback after failures involving NODELETE objects (bug 20839).
|
|
||||||
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <https://www.gnu.org/licenses/>. */
|
|
||||||
+
|
|
||||||
+#include <dlfcn.h>
|
|
||||||
+#include <errno.h>
|
|
||||||
+#include <gnu/lib-names.h>
|
|
||||||
+#include <stddef.h>
|
|
||||||
+#include <stdio.h>
|
|
||||||
+#include <string.h>
|
|
||||||
+#include <support/check.h>
|
|
||||||
+#include <support/xdlfcn.h>
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+do_test (void)
|
|
||||||
+{
|
|
||||||
+ /* This test uses libpthread as the canonical NODELETE module. If
|
|
||||||
+ libpthread is no longer NODELETE because it has been merged into
|
|
||||||
+ libc, the test needs to be updated. */
|
|
||||||
+ TEST_VERIFY (dlsym (NULL, "pthread_create") == NULL);
|
|
||||||
+
|
|
||||||
+ /* This is expected to fail because of the missing dependency. */
|
|
||||||
+ puts ("info: attempting to load tst-dlopenfailmod1.so");
|
|
||||||
+ TEST_VERIFY (dlopen ("tst-dlopenfailmod1.so", RTLD_LAZY) == NULL);
|
|
||||||
+ const char *message = dlerror ();
|
|
||||||
+ TEST_COMPARE_STRING (message,
|
|
||||||
+ "tst-dlopenfail-missingmod.so:"
|
|
||||||
+ " cannot open shared object file:"
|
|
||||||
+ " No such file or directory");
|
|
||||||
+
|
|
||||||
+ /* Do not probe for the presence of libpthread at this point because
|
|
||||||
+ that might trigger relocation if bug 20839 is present, obscuring
|
|
||||||
+ a subsequent crash. */
|
|
||||||
+
|
|
||||||
+ /* This is expected to succeed. */
|
|
||||||
+ puts ("info: loading tst-dlopenfailmod2.so");
|
|
||||||
+ void *handle = xdlopen ("tst-dlopenfailmod2.so", RTLD_NOW);
|
|
||||||
+ xdlclose (handle);
|
|
||||||
+
|
|
||||||
+ /* libpthread should remain loaded. */
|
|
||||||
+ TEST_VERIFY (dlopen (LIBPTHREAD_SO, RTLD_LAZY | RTLD_NOLOAD) != NULL);
|
|
||||||
+ TEST_VERIFY (dlsym (NULL, "pthread_create") == NULL);
|
|
||||||
+
|
|
||||||
+ /* We can make libpthread global, and then the symbol should become
|
|
||||||
+ available. */
|
|
||||||
+ TEST_VERIFY (dlopen (LIBPTHREAD_SO, RTLD_LAZY | RTLD_GLOBAL) != NULL);
|
|
||||||
+ TEST_VERIFY (dlsym (NULL, "pthread_create") != NULL);
|
|
||||||
+
|
|
||||||
+ /* sem_open is sufficiently complex to depend on relocations. */
|
|
||||||
+ void *(*sem_open_ptr) (const char *, int flag, ...)
|
|
||||||
+ = dlsym (NULL, "sem_open");
|
|
||||||
+ if (sem_open_ptr == NULL)
|
|
||||||
+ /* Hurd does not implement sem_open. */
|
|
||||||
+ puts ("warning: sem_open not found, further testing not possible");
|
|
||||||
+ else
|
|
||||||
+ {
|
|
||||||
+ errno = 0;
|
|
||||||
+ TEST_VERIFY (sem_open_ptr ("/", 0) == NULL);
|
|
||||||
+ TEST_COMPARE (errno, EINVAL);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#include <support/test-driver.c>
|
|
||||||
diff --git a/elf/tst-dlopenfaillinkmod.c b/elf/tst-dlopenfaillinkmod.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000..3b14b02bc9a12c0b
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/elf/tst-dlopenfaillinkmod.c
|
|
||||||
@@ -0,0 +1,17 @@
|
|
||||||
+/* Empty module with a soname which is not available at run time.
|
|
||||||
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <https://www.gnu.org/licenses/>. */
|
|
||||||
diff --git a/elf/tst-dlopenfailmod1.c b/elf/tst-dlopenfailmod1.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000..6ef48829899a5a64
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/elf/tst-dlopenfailmod1.c
|
|
||||||
@@ -0,0 +1,36 @@
|
|
||||||
+/* Module which depends on two modules: one NODELETE, one missing.
|
|
||||||
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <https://www.gnu.org/licenses/>. */
|
|
||||||
+
|
|
||||||
+/* Note: Due to the missing second module, this object cannot be
|
|
||||||
+ loaded at run time. */
|
|
||||||
+
|
|
||||||
+#include <pthread.h>
|
|
||||||
+#include <stdio.h>
|
|
||||||
+#include <unistd.h>
|
|
||||||
+
|
|
||||||
+/* Force linking against libpthread. */
|
|
||||||
+void *pthread_create_reference = pthread_create;
|
|
||||||
+
|
|
||||||
+/* The constructor will never be executed because the module cannot be
|
|
||||||
+ loaded. */
|
|
||||||
+static void __attribute__ ((constructor))
|
|
||||||
+init (void)
|
|
||||||
+{
|
|
||||||
+ puts ("tst-dlopenfailmod1 constructor executed");
|
|
||||||
+ _exit (1);
|
|
||||||
+}
|
|
||||||
diff --git a/elf/tst-dlopenfailmod2.c b/elf/tst-dlopenfailmod2.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000..7d600386c13b98bd
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/elf/tst-dlopenfailmod2.c
|
|
||||||
@@ -0,0 +1,29 @@
|
|
||||||
+/* Module which depends on on a NODELETE module, and can be loaded.
|
|
||||||
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <https://www.gnu.org/licenses/>. */
|
|
||||||
+
|
|
||||||
+#include <pthread.h>
|
|
||||||
+#include <stdio.h>
|
|
||||||
+
|
|
||||||
+/* Force linking against libpthread. */
|
|
||||||
+void *pthread_create_reference = pthread_create;
|
|
||||||
+
|
|
||||||
+static void __attribute__ ((constructor))
|
|
||||||
+init (void)
|
|
||||||
+{
|
|
||||||
+ puts ("info: tst-dlopenfailmod2.so constructor invoked");
|
|
||||||
+}
|
|
||||||
diff --git a/include/link.h b/include/link.h
|
|
||||||
index 83b1c34b7b4db8f3..a277b77cad6b52b1 100644
|
|
||||||
--- a/include/link.h
|
|
||||||
+++ b/include/link.h
|
|
||||||
@@ -79,6 +79,21 @@ struct r_search_path_struct
|
|
||||||
int malloced;
|
|
||||||
};
|
|
||||||
|
|
||||||
+/* Type used by the l_nodelete member. */
|
|
||||||
+enum link_map_nodelete
|
|
||||||
+{
|
|
||||||
+ /* This link map can be deallocated. */
|
|
||||||
+ link_map_nodelete_inactive = 0, /* Zero-initialized in _dl_new_object. */
|
|
||||||
+
|
|
||||||
+ /* This link map cannot be deallocated. */
|
|
||||||
+ link_map_nodelete_active,
|
|
||||||
+
|
|
||||||
+ /* This link map cannot be deallocated after dlopen has succeded.
|
|
||||||
+ dlopen turns this into link_map_nodelete_active. dlclose treats
|
|
||||||
+ this intermediate state as link_map_nodelete_active. */
|
|
||||||
+ link_map_nodelete_pending,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
|
|
||||||
/* Structure describing a loaded shared object. The `l_next' and `l_prev'
|
|
||||||
members form a chain of all the shared objects loaded at startup.
|
|
||||||
@@ -203,6 +218,11 @@ struct link_map
|
|
||||||
freed, ie. not allocated with
|
|
||||||
the dummy malloc in ld.so. */
|
|
||||||
|
|
||||||
+ /* Actually of type enum link_map_nodelete. Separate byte due to
|
|
||||||
+ a read in add_dependency in elf/dl-lookup.c outside the loader
|
|
||||||
+ lock. Only valid for l_type == lt_loaded. */
|
|
||||||
+ unsigned char l_nodelete;
|
|
||||||
+
|
|
||||||
#include <link_map.h>
|
|
||||||
|
|
||||||
/* Collected information about own RPATH directories. */
|
|
@ -1,104 +0,0 @@
|
|||||||
commit a2e8aa0d9ea648068d8be52dd7b15f1b6a008e23
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Thu Oct 31 19:30:19 2019 +0100
|
|
||||||
|
|
||||||
Block signals during the initial part of dlopen
|
|
||||||
|
|
||||||
Lazy binding in a signal handler that interrupts a dlopen sees
|
|
||||||
intermediate dynamic linker state. This has likely been always
|
|
||||||
unsafe, but with the new pending NODELETE state, this is clearly
|
|
||||||
incorrect. Other threads are excluded via the loader lock, but the
|
|
||||||
current thread is not. Blocking signals until right before ELF
|
|
||||||
constructors run is the safe thing to do.
|
|
||||||
|
|
||||||
Change-Id: Iad079080ebe7442c13313ba11dc2797953faef35
|
|
||||||
|
|
||||||
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
|
||||||
index 79c6e4c8ed1c9dfa..25838b073ac1edaf 100644
|
|
||||||
--- a/elf/dl-open.c
|
|
||||||
+++ b/elf/dl-open.c
|
|
||||||
@@ -34,6 +34,7 @@
|
|
||||||
#include <atomic.h>
|
|
||||||
#include <libc-internal.h>
|
|
||||||
#include <array_length.h>
|
|
||||||
+#include <internal-signals.h>
|
|
||||||
|
|
||||||
#include <dl-dst.h>
|
|
||||||
#include <dl-prop.h>
|
|
||||||
@@ -52,6 +53,10 @@ struct dl_open_args
|
|
||||||
/* Namespace ID. */
|
|
||||||
Lmid_t nsid;
|
|
||||||
|
|
||||||
+ /* Original signal mask. Used for unblocking signal handlers before
|
|
||||||
+ running ELF constructors. */
|
|
||||||
+ sigset_t original_signal_mask;
|
|
||||||
+
|
|
||||||
/* Original value of _ns_global_scope_pending_adds. Set by
|
|
||||||
dl_open_worker. Only valid if nsid is a real namespace
|
|
||||||
(non-negative). */
|
|
||||||
@@ -524,12 +529,16 @@ dl_open_worker (void *a)
|
|
||||||
if (new == NULL)
|
|
||||||
{
|
|
||||||
assert (mode & RTLD_NOLOAD);
|
|
||||||
+ __libc_signal_restore_set (&args->original_signal_mask);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (__glibc_unlikely (mode & __RTLD_SPROF))
|
|
||||||
- /* This happens only if we load a DSO for 'sprof'. */
|
|
||||||
- return;
|
|
||||||
+ {
|
|
||||||
+ /* This happens only if we load a DSO for 'sprof'. */
|
|
||||||
+ __libc_signal_restore_set (&args->original_signal_mask);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
/* This object is directly loaded. */
|
|
||||||
++new->l_direct_opencount;
|
|
||||||
@@ -565,6 +574,7 @@ dl_open_worker (void *a)
|
|
||||||
|
|
||||||
assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT);
|
|
||||||
|
|
||||||
+ __libc_signal_restore_set (&args->original_signal_mask);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -745,6 +755,10 @@ dl_open_worker (void *a)
|
|
||||||
if (mode & RTLD_GLOBAL)
|
|
||||||
add_to_global_resize (new);
|
|
||||||
|
|
||||||
+ /* Unblock signals. Data structures are now consistent, and
|
|
||||||
+ application code may run. */
|
|
||||||
+ __libc_signal_restore_set (&args->original_signal_mask);
|
|
||||||
+
|
|
||||||
/* Run the initializer functions of new objects. Temporarily
|
|
||||||
disable the exception handler, so that lazy binding failures are
|
|
||||||
fatal. */
|
|
||||||
@@ -834,6 +848,10 @@ no more namespaces available for dlmopen()"));
|
|
||||||
args.argv = argv;
|
|
||||||
args.env = env;
|
|
||||||
|
|
||||||
+ /* Recursive lazy binding during manipulation of the dynamic loader
|
|
||||||
+ structures may result in incorrect behavior. */
|
|
||||||
+ __libc_signal_block_all (&args.original_signal_mask);
|
|
||||||
+
|
|
||||||
struct dl_exception exception;
|
|
||||||
int errcode = _dl_catch_exception (&exception, dl_open_worker, &args);
|
|
||||||
|
|
||||||
@@ -874,10 +892,16 @@ no more namespaces available for dlmopen()"));
|
|
||||||
|
|
||||||
_dl_close_worker (args.map, true);
|
|
||||||
|
|
||||||
+ /* Restore the signal mask. In the success case, this
|
|
||||||
+ happens inside dl_open_worker. */
|
|
||||||
+ __libc_signal_restore_set (&args.original_signal_mask);
|
|
||||||
+
|
|
||||||
/* All link_map_nodelete_pending objects should have been
|
|
||||||
deleted at this point, which is why it is not necessary
|
|
||||||
to reset the flag here. */
|
|
||||||
}
|
|
||||||
+ else
|
|
||||||
+ __libc_signal_restore_set (&args.original_signal_mask);
|
|
||||||
|
|
||||||
assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT);
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
|||||||
Please see the following bug for a complete summary:
|
|
||||||
https://bugzilla.redhat.com/show_bug.cgi?id=1615608
|
|
||||||
|
|
||||||
Index: glibc-2.28/manual/startup.texi
|
|
||||||
===================================================================
|
|
||||||
--- glibc-2.28.orig/manual/startup.texi
|
|
||||||
+++ glibc-2.28/manual/startup.texi
|
|
||||||
@@ -1005,14 +1005,6 @@ This function actually terminates the pr
|
|
||||||
intercept this signal; see @ref{Signal Handling}.
|
|
||||||
@end deftypefun
|
|
||||||
|
|
||||||
-@c Put in by rms. Don't remove.
|
|
||||||
-@cartouche
|
|
||||||
-@strong{Future Change Warning:} Proposed Federal censorship regulations
|
|
||||||
-may prohibit us from giving you information about the possibility of
|
|
||||||
-calling this function. We would be required to say that this is not an
|
|
||||||
-acceptable way of terminating a program.
|
|
||||||
-@end cartouche
|
|
||||||
-
|
|
||||||
@node Termination Internals
|
|
||||||
@subsection Termination Internals
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
|||||||
Patch by Hanataka Shinya <hanataka.shinya@gmail.com> from
|
|
||||||
<https://sourceware.org/bugzilla/show_bug.cgi?id=24405>. Confirmed by TAMUKI
|
|
||||||
Shoichi's patch in
|
|
||||||
<https://sourceware.org/ml/libc-alpha/2019-04/msg00005.html>.
|
|
||||||
|
|
||||||
The official announcement by the Japanese Prime Minister in
|
|
||||||
<https://www.kantei.go.jp/jp/tyoukanpress/201904/1_a.html> uses U+4EE4 U+548C
|
|
||||||
as well.
|
|
||||||
|
|
||||||
diff --git a/localedata/locales/ja_JP b/localedata/locales/ja_JP
|
|
||||||
index 1fd2fee44b2879d9..30190b624856cc53 100644
|
|
||||||
--- a/localedata/locales/ja_JP
|
|
||||||
+++ b/localedata/locales/ja_JP
|
|
||||||
@@ -14946,7 +14946,9 @@ am_pm "<U5348><U524D>";"<U5348><U5F8C>"
|
|
||||||
|
|
||||||
t_fmt_ampm "%p%I<U6642>%M<U5206>%S<U79D2>"
|
|
||||||
|
|
||||||
-era "+:2:1990//01//01:+*:<U5E73><U6210>:%EC%Ey<U5E74>";/
|
|
||||||
+era "+:2:2020//01//01:+*:<U4EE4><U548C>:%EC%Ey<U5E74>";/
|
|
||||||
+ "+:1:2019//05//01:2019//12//31:<U4EE4><U548C>:%EC<U5143><U5E74>";/
|
|
||||||
+ "+:2:1990//01//01:2019//04//30:<U5E73><U6210>:%EC%Ey<U5E74>";/
|
|
||||||
"+:1:1989//01//08:1989//12//31:<U5E73><U6210>:%EC<U5143><U5E74>";/
|
|
||||||
"+:2:1927//01//01:1989//01//07:<U662D><U548C>:%EC%Ey<U5E74>";/
|
|
||||||
"+:1:1926//12//25:1926//12//31:<U662D><U548C>:%EC<U5143><U5E74>";/
|
|
@ -1,254 +0,0 @@
|
|||||||
commit 4b25485f03158959cff45379eecc1d73c7dcdd11
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Fri Aug 10 11:19:26 2018 +0200
|
|
||||||
|
|
||||||
Linux: Rewrite __old_getdents64 [BZ #23497]
|
|
||||||
|
|
||||||
Commit 298d0e3129c0b5137f4989275b13fe30d0733c4d ("Consolidate Linux
|
|
||||||
getdents{64} implementation") broke the implementation because it does
|
|
||||||
not take into account struct offset differences.
|
|
||||||
|
|
||||||
The new implementation is close to the old one, before the
|
|
||||||
consolidation, but has been cleaned up slightly.
|
|
||||||
|
|
||||||
(cherry picked from commit 690652882b499defb3d950dfeff8fe421d13cab5)
|
|
||||||
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
|
|
||||||
index f71cc39c7e257a0a..773aaea0e980bdd6 100644
|
|
||||||
--- a/sysdeps/unix/sysv/linux/Makefile
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/Makefile
|
|
||||||
@@ -161,6 +161,7 @@ inhibit-glue = yes
|
|
||||||
|
|
||||||
ifeq ($(subdir),dirent)
|
|
||||||
sysdep_routines += getdirentries getdirentries64
|
|
||||||
+tests-internal += tst-readdir64-compat
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(subdir),nis)
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/getdents64.c b/sysdeps/unix/sysv/linux/getdents64.c
|
|
||||||
index 3bde0cf4f0226f95..bc140b5a7fac3040 100644
|
|
||||||
--- a/sysdeps/unix/sysv/linux/getdents64.c
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/getdents64.c
|
|
||||||
@@ -33,41 +33,80 @@ strong_alias (__getdents64, __getdents)
|
|
||||||
# include <shlib-compat.h>
|
|
||||||
|
|
||||||
# if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
|
|
||||||
-# include <olddirent.h>
|
|
||||||
+# include <olddirent.h>
|
|
||||||
+# include <unistd.h>
|
|
||||||
|
|
||||||
-/* kernel definition of as of 3.2. */
|
|
||||||
-struct compat_linux_dirent
|
|
||||||
+static ssize_t
|
|
||||||
+handle_overflow (int fd, __off64_t offset, ssize_t count)
|
|
||||||
{
|
|
||||||
- /* Both d_ino and d_off are compat_ulong_t which are defined in all
|
|
||||||
- architectures as 'u32'. */
|
|
||||||
- uint32_t d_ino;
|
|
||||||
- uint32_t d_off;
|
|
||||||
- unsigned short d_reclen;
|
|
||||||
- char d_name[1];
|
|
||||||
-};
|
|
||||||
+ /* If this is the first entry in the buffer, we can report the
|
|
||||||
+ error. */
|
|
||||||
+ if (count == 0)
|
|
||||||
+ {
|
|
||||||
+ __set_errno (EOVERFLOW);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Otherwise, seek to the overflowing entry, so that the next call
|
|
||||||
+ will report the error, and return the data read so far.. */
|
|
||||||
+ if (__lseek64 (fd, offset, SEEK_SET) != 0)
|
|
||||||
+ return -1;
|
|
||||||
+ return count;
|
|
||||||
+}
|
|
||||||
|
|
||||||
ssize_t
|
|
||||||
__old_getdents64 (int fd, char *buf, size_t nbytes)
|
|
||||||
{
|
|
||||||
- ssize_t retval = INLINE_SYSCALL_CALL (getdents, fd, buf, nbytes);
|
|
||||||
+ /* We do not move the individual directory entries. This is only
|
|
||||||
+ possible if the target type (struct __old_dirent64) is smaller
|
|
||||||
+ than the source type. */
|
|
||||||
+ _Static_assert (offsetof (struct __old_dirent64, d_name)
|
|
||||||
+ <= offsetof (struct dirent64, d_name),
|
|
||||||
+ "__old_dirent64 is larger than dirent64");
|
|
||||||
+ _Static_assert (__alignof__ (struct __old_dirent64)
|
|
||||||
+ <= __alignof__ (struct dirent64),
|
|
||||||
+ "alignment of __old_dirent64 is larger than dirent64");
|
|
||||||
|
|
||||||
- /* The kernel added the d_type value after the name. Change this now. */
|
|
||||||
- if (retval != -1)
|
|
||||||
+ ssize_t retval = INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes);
|
|
||||||
+ if (retval > 0)
|
|
||||||
{
|
|
||||||
- union
|
|
||||||
- {
|
|
||||||
- struct compat_linux_dirent k;
|
|
||||||
- struct dirent u;
|
|
||||||
- } *kbuf = (void *) buf;
|
|
||||||
-
|
|
||||||
- while ((char *) kbuf < buf + retval)
|
|
||||||
+ char *p = buf;
|
|
||||||
+ char *end = buf + retval;
|
|
||||||
+ while (p < end)
|
|
||||||
{
|
|
||||||
- char d_type = *((char *) kbuf + kbuf->k.d_reclen - 1);
|
|
||||||
- memmove (kbuf->u.d_name, kbuf->k.d_name,
|
|
||||||
- strlen (kbuf->k.d_name) + 1);
|
|
||||||
- kbuf->u.d_type = d_type;
|
|
||||||
+ struct dirent64 *source = (struct dirent64 *) p;
|
|
||||||
+
|
|
||||||
+ /* Copy out the fixed-size data. */
|
|
||||||
+ __ino_t ino = source->d_ino;
|
|
||||||
+ __off64_t offset = source->d_off;
|
|
||||||
+ unsigned int reclen = source->d_reclen;
|
|
||||||
+ unsigned char type = source->d_type;
|
|
||||||
+
|
|
||||||
+ /* Check for ino_t overflow. */
|
|
||||||
+ if (__glibc_unlikely (ino != source->d_ino))
|
|
||||||
+ return handle_overflow (fd, offset, p - buf);
|
|
||||||
+
|
|
||||||
+ /* Convert to the target layout. Use a separate struct and
|
|
||||||
+ memcpy to side-step aliasing issues. */
|
|
||||||
+ struct __old_dirent64 result;
|
|
||||||
+ result.d_ino = ino;
|
|
||||||
+ result.d_off = offset;
|
|
||||||
+ result.d_reclen = reclen;
|
|
||||||
+ result.d_type = type;
|
|
||||||
+
|
|
||||||
+ /* Write the fixed-sized part of the result to the
|
|
||||||
+ buffer. */
|
|
||||||
+ size_t result_name_offset = offsetof (struct __old_dirent64, d_name);
|
|
||||||
+ memcpy (p, &result, result_name_offset);
|
|
||||||
+
|
|
||||||
+ /* Adjust the position of the name if necessary. Copy
|
|
||||||
+ everything until the end of the record, including the
|
|
||||||
+ terminating NUL byte. */
|
|
||||||
+ if (result_name_offset != offsetof (struct dirent64, d_name))
|
|
||||||
+ memmove (p + result_name_offset, source->d_name,
|
|
||||||
+ reclen - offsetof (struct dirent64, d_name));
|
|
||||||
|
|
||||||
- kbuf = (void *) ((char *) kbuf + kbuf->k.d_reclen);
|
|
||||||
+ p += reclen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/tst-readdir64-compat.c b/sysdeps/unix/sysv/linux/tst-readdir64-compat.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000..43c4a8477c7403c5
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/tst-readdir64-compat.c
|
|
||||||
@@ -0,0 +1,111 @@
|
|
||||||
+/* Test readdir64 compatibility symbol.
|
|
||||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <http://www.gnu.org/licenses/>. */
|
|
||||||
+
|
|
||||||
+#include <dirent.h>
|
|
||||||
+#include <dlfcn.h>
|
|
||||||
+#include <errno.h>
|
|
||||||
+#include <shlib-compat.h>
|
|
||||||
+#include <stdbool.h>
|
|
||||||
+#include <stdio.h>
|
|
||||||
+#include <string.h>
|
|
||||||
+#include <support/check.h>
|
|
||||||
+
|
|
||||||
+/* Copied from <olddirent.h>. */
|
|
||||||
+struct __old_dirent64
|
|
||||||
+ {
|
|
||||||
+ __ino_t d_ino;
|
|
||||||
+ __off64_t d_off;
|
|
||||||
+ unsigned short int d_reclen;
|
|
||||||
+ unsigned char d_type;
|
|
||||||
+ char d_name[256];
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+typedef struct __old_dirent64 *(*compat_readdir64_type) (DIR *);
|
|
||||||
+
|
|
||||||
+#if TEST_COMPAT (libc, GLIBC_2_1, GLIBC_2_2)
|
|
||||||
+struct __old_dirent64 *compat_readdir64 (DIR *);
|
|
||||||
+compat_symbol_reference (libc, compat_readdir64, readdir64, GLIBC_2_1);
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+do_test (void)
|
|
||||||
+{
|
|
||||||
+#if TEST_COMPAT (libc, GLIBC_2_1, GLIBC_2_2)
|
|
||||||
+
|
|
||||||
+ /* Directory stream using the non-compat readdir64 symbol. The test
|
|
||||||
+ checks against this. */
|
|
||||||
+ DIR *dir_reference = opendir (".");
|
|
||||||
+ TEST_VERIFY_EXIT (dir_reference != NULL);
|
|
||||||
+ DIR *dir_test = opendir (".");
|
|
||||||
+ TEST_VERIFY_EXIT (dir_test != NULL);
|
|
||||||
+
|
|
||||||
+ /* This loop assumes that the enumeration order is consistent for
|
|
||||||
+ two different handles. Nothing should write to the current
|
|
||||||
+ directory (in the source tree) while this test runs, so there
|
|
||||||
+ should not be any difference due to races. */
|
|
||||||
+ size_t count = 0;
|
|
||||||
+ while (true)
|
|
||||||
+ {
|
|
||||||
+ errno = 0;
|
|
||||||
+ struct dirent64 *entry_reference = readdir64 (dir_reference);
|
|
||||||
+ if (entry_reference == NULL && errno != 0)
|
|
||||||
+ FAIL_EXIT1 ("readdir64 entry %zu: %m\n", count);
|
|
||||||
+ struct __old_dirent64 *entry_test = compat_readdir64 (dir_test);
|
|
||||||
+ if (entry_reference == NULL)
|
|
||||||
+ {
|
|
||||||
+ if (errno == EOVERFLOW)
|
|
||||||
+ {
|
|
||||||
+ TEST_VERIFY (entry_reference->d_ino
|
|
||||||
+ != (__ino_t) entry_reference->d_ino);
|
|
||||||
+ printf ("info: inode number overflow at entry %zu\n", count);
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ if (errno != 0)
|
|
||||||
+ FAIL_EXIT1 ("compat readdir64 entry %zu: %m\n", count);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Check that both streams end at the same time. */
|
|
||||||
+ if (entry_reference == NULL)
|
|
||||||
+ {
|
|
||||||
+ TEST_VERIFY (entry_test == NULL);
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ TEST_VERIFY_EXIT (entry_test != NULL);
|
|
||||||
+
|
|
||||||
+ /* Check that the entries are the same. */
|
|
||||||
+ TEST_COMPARE_BLOB (entry_reference->d_name,
|
|
||||||
+ strlen (entry_reference->d_name),
|
|
||||||
+ entry_test->d_name, strlen (entry_test->d_name));
|
|
||||||
+ TEST_COMPARE (entry_reference->d_ino, entry_test->d_ino);
|
|
||||||
+ TEST_COMPARE (entry_reference->d_off, entry_test->d_off);
|
|
||||||
+ TEST_COMPARE (entry_reference->d_type, entry_test->d_type);
|
|
||||||
+ TEST_COMPARE (entry_reference->d_reclen, entry_test->d_reclen);
|
|
||||||
+
|
|
||||||
+ ++count;
|
|
||||||
+ }
|
|
||||||
+ printf ("info: %zu directory entries found\n", count);
|
|
||||||
+ TEST_VERIFY (count >= 3); /* ".", "..", and some source files. */
|
|
||||||
+
|
|
||||||
+ TEST_COMPARE (closedir (dir_test), 0);
|
|
||||||
+ TEST_COMPARE (closedir (dir_reference), 0);
|
|
||||||
+#endif
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#include <support/test-driver.c>
|
|
@ -1,154 +0,0 @@
|
|||||||
commit d524fa6c35e675eedbd8fe6cdf4db0b49c658026
|
|
||||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
|
||||||
Date: Thu Nov 8 10:06:58 2018 -0800
|
|
||||||
|
|
||||||
Check multiple NT_GNU_PROPERTY_TYPE_0 notes [BZ #23509]
|
|
||||||
|
|
||||||
Linkers group input note sections with the same name into one output
|
|
||||||
note section with the same name. One output note section is placed in
|
|
||||||
one PT_NOTE segment. Since new linkers merge input .note.gnu.property
|
|
||||||
sections into one output .note.gnu.property section, there is only
|
|
||||||
one NT_GNU_PROPERTY_TYPE_0 note in one PT_NOTE segment with new linkers.
|
|
||||||
Since older linkers treat input .note.gnu.property section as a generic
|
|
||||||
note section and just concatenate all input .note.gnu.property sections
|
|
||||||
into one output .note.gnu.property section without merging them, we may
|
|
||||||
see multiple NT_GNU_PROPERTY_TYPE_0 notes in one PT_NOTE segment with
|
|
||||||
older linkers.
|
|
||||||
|
|
||||||
When an older linker is used to created the program on CET-enabled OS,
|
|
||||||
the linker output has a single .note.gnu.property section with multiple
|
|
||||||
NT_GNU_PROPERTY_TYPE_0 notes, some of which have IBT and SHSTK enable
|
|
||||||
bits set even if the program isn't CET enabled. Such programs will
|
|
||||||
crash on CET-enabled machines. This patch updates the note parser:
|
|
||||||
|
|
||||||
1. Skip note parsing if a NT_GNU_PROPERTY_TYPE_0 note has been processed.
|
|
||||||
2. Check multiple NT_GNU_PROPERTY_TYPE_0 notes.
|
|
||||||
|
|
||||||
[BZ #23509]
|
|
||||||
* sysdeps/x86/dl-prop.h (_dl_process_cet_property_note): Skip
|
|
||||||
note parsing if a NT_GNU_PROPERTY_TYPE_0 note has been processed.
|
|
||||||
Update the l_cet field when processing NT_GNU_PROPERTY_TYPE_0 note.
|
|
||||||
Check multiple NT_GNU_PROPERTY_TYPE_0 notes.
|
|
||||||
* sysdeps/x86/link_map.h (l_cet): Expand to 3 bits, Add
|
|
||||||
lc_unknown.
|
|
||||||
|
|
||||||
diff --git a/sysdeps/x86/dl-prop.h b/sysdeps/x86/dl-prop.h
|
|
||||||
index 26c3131ac5e2d080..9ab890d12bb99133 100644
|
|
||||||
--- a/sysdeps/x86/dl-prop.h
|
|
||||||
+++ b/sysdeps/x86/dl-prop.h
|
|
||||||
@@ -49,6 +49,10 @@ _dl_process_cet_property_note (struct link_map *l,
|
|
||||||
const ElfW(Addr) align)
|
|
||||||
{
|
|
||||||
#if CET_ENABLED
|
|
||||||
+ /* Skip if we have seen a NT_GNU_PROPERTY_TYPE_0 note before. */
|
|
||||||
+ if (l->l_cet != lc_unknown)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
/* The NT_GNU_PROPERTY_TYPE_0 note must be aliged to 4 bytes in
|
|
||||||
32-bit objects and to 8 bytes in 64-bit objects. Skip notes
|
|
||||||
with incorrect alignment. */
|
|
||||||
@@ -57,6 +61,9 @@ _dl_process_cet_property_note (struct link_map *l,
|
|
||||||
|
|
||||||
const ElfW(Addr) start = (ElfW(Addr)) note;
|
|
||||||
|
|
||||||
+ unsigned int feature_1 = 0;
|
|
||||||
+ unsigned int last_type = 0;
|
|
||||||
+
|
|
||||||
while ((ElfW(Addr)) (note + 1) - start < size)
|
|
||||||
{
|
|
||||||
/* Find the NT_GNU_PROPERTY_TYPE_0 note. */
|
|
||||||
@@ -64,10 +71,18 @@ _dl_process_cet_property_note (struct link_map *l,
|
|
||||||
&& note->n_type == NT_GNU_PROPERTY_TYPE_0
|
|
||||||
&& memcmp (note + 1, "GNU", 4) == 0)
|
|
||||||
{
|
|
||||||
+ /* Stop if we see more than one GNU property note which may
|
|
||||||
+ be generated by the older linker. */
|
|
||||||
+ if (l->l_cet != lc_unknown)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ /* Check CET status now. */
|
|
||||||
+ l->l_cet = lc_none;
|
|
||||||
+
|
|
||||||
/* Check for invalid property. */
|
|
||||||
if (note->n_descsz < 8
|
|
||||||
|| (note->n_descsz % sizeof (ElfW(Addr))) != 0)
|
|
||||||
- break;
|
|
||||||
+ return;
|
|
||||||
|
|
||||||
/* Start and end of property array. */
|
|
||||||
unsigned char *ptr = (unsigned char *) (note + 1) + 4;
|
|
||||||
@@ -78,9 +93,15 @@ _dl_process_cet_property_note (struct link_map *l,
|
|
||||||
unsigned int type = *(unsigned int *) ptr;
|
|
||||||
unsigned int datasz = *(unsigned int *) (ptr + 4);
|
|
||||||
|
|
||||||
+ /* Property type must be in ascending order. */
|
|
||||||
+ if (type < last_type)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
ptr += 8;
|
|
||||||
if ((ptr + datasz) > ptr_end)
|
|
||||||
- break;
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ last_type = type;
|
|
||||||
|
|
||||||
if (type == GNU_PROPERTY_X86_FEATURE_1_AND)
|
|
||||||
{
|
|
||||||
@@ -89,14 +110,18 @@ _dl_process_cet_property_note (struct link_map *l,
|
|
||||||
we stop the search regardless if its size is correct
|
|
||||||
or not. There is no point to continue if this note
|
|
||||||
is ill-formed. */
|
|
||||||
- if (datasz == 4)
|
|
||||||
- {
|
|
||||||
- unsigned int feature_1 = *(unsigned int *) ptr;
|
|
||||||
- if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_IBT))
|
|
||||||
- l->l_cet |= lc_ibt;
|
|
||||||
- if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_SHSTK))
|
|
||||||
- l->l_cet |= lc_shstk;
|
|
||||||
- }
|
|
||||||
+ if (datasz != 4)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ feature_1 = *(unsigned int *) ptr;
|
|
||||||
+
|
|
||||||
+ /* Keep searching for the next GNU property note
|
|
||||||
+ generated by the older linker. */
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ else if (type > GNU_PROPERTY_X86_FEATURE_1_AND)
|
|
||||||
+ {
|
|
||||||
+ /* Stop since property type is in ascending order. */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -112,6 +137,12 @@ _dl_process_cet_property_note (struct link_map *l,
|
|
||||||
+ ELF_NOTE_NEXT_OFFSET (note->n_namesz, note->n_descsz,
|
|
||||||
align));
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ /* We get here only if there is one or no GNU property note. */
|
|
||||||
+ if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_IBT))
|
|
||||||
+ l->l_cet |= lc_ibt;
|
|
||||||
+ if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_SHSTK))
|
|
||||||
+ l->l_cet |= lc_shstk;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/sysdeps/x86/link_map.h b/sysdeps/x86/link_map.h
|
|
||||||
index ef1206a9d2396a6f..9367ed08896794a4 100644
|
|
||||||
--- a/sysdeps/x86/link_map.h
|
|
||||||
+++ b/sysdeps/x86/link_map.h
|
|
||||||
@@ -19,8 +19,9 @@
|
|
||||||
/* If this object is enabled with CET. */
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
- lc_none = 0, /* Not enabled with CET. */
|
|
||||||
- lc_ibt = 1 << 0, /* Enabled with IBT. */
|
|
||||||
- lc_shstk = 1 << 1, /* Enabled with STSHK. */
|
|
||||||
+ lc_unknown = 0, /* Unknown CET status. */
|
|
||||||
+ lc_none = 1 << 0, /* Not enabled with CET. */
|
|
||||||
+ lc_ibt = 1 << 1, /* Enabled with IBT. */
|
|
||||||
+ lc_shstk = 1 << 2, /* Enabled with STSHK. */
|
|
||||||
lc_ibt_and_shstk = lc_ibt | lc_shstk /* Enabled with both. */
|
|
||||||
- } l_cet:2;
|
|
||||||
+ } l_cet:3;
|
|
@ -1,28 +0,0 @@
|
|||||||
commit d05b05d1570ba3ae354a2f5a3cfeefb373b09979
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Mon Aug 13 14:28:07 2018 +0200
|
|
||||||
|
|
||||||
error, error_at_line: Add missing va_end calls
|
|
||||||
|
|
||||||
(cherry picked from commit b7b52b9dec337a08a89bc67638773be652eba332)
|
|
||||||
|
|
||||||
diff --git a/misc/error.c b/misc/error.c
|
|
||||||
index b4e8b6c93886b737..03378e2f2aa6251e 100644
|
|
||||||
--- a/misc/error.c
|
|
||||||
+++ b/misc/error.c
|
|
||||||
@@ -319,6 +319,7 @@ error (int status, int errnum, const char *message, ...)
|
|
||||||
|
|
||||||
va_start (args, message);
|
|
||||||
error_tail (status, errnum, message, args);
|
|
||||||
+ va_end (args);
|
|
||||||
|
|
||||||
#ifdef _LIBC
|
|
||||||
_IO_funlockfile (stderr);
|
|
||||||
@@ -390,6 +391,7 @@ error_at_line (int status, int errnum, const char *file_name,
|
|
||||||
|
|
||||||
va_start (args, message);
|
|
||||||
error_tail (status, errnum, message, args);
|
|
||||||
+ va_end (args);
|
|
||||||
|
|
||||||
#ifdef _LIBC
|
|
||||||
_IO_funlockfile (stderr);
|
|
@ -1,35 +0,0 @@
|
|||||||
commit bfcfa22589f2b4277a65e60c6b736b6bbfbd87d0
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Tue Aug 14 10:51:07 2018 +0200
|
|
||||||
|
|
||||||
nscd: Deallocate existing user names in file parser
|
|
||||||
|
|
||||||
This avoids a theoretical memory leak (theoretical because it depends on
|
|
||||||
multiple server-user/stat-user directives in the configuration file).
|
|
||||||
|
|
||||||
(cherry picked from commit 2d7acfac3ebf266dcbc82d0d6cc576f626953a03)
|
|
||||||
|
|
||||||
diff --git a/nscd/nscd_conf.c b/nscd/nscd_conf.c
|
|
||||||
index 265a02434dd26c29..7293b795b6bcf71e 100644
|
|
||||||
--- a/nscd/nscd_conf.c
|
|
||||||
+++ b/nscd/nscd_conf.c
|
|
||||||
@@ -190,7 +190,10 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb])
|
|
||||||
if (!arg1)
|
|
||||||
error (0, 0, _("Must specify user name for server-user option"));
|
|
||||||
else
|
|
||||||
- server_user = xstrdup (arg1);
|
|
||||||
+ {
|
|
||||||
+ free ((char *) server_user);
|
|
||||||
+ server_user = xstrdup (arg1);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
else if (strcmp (entry, "stat-user") == 0)
|
|
||||||
{
|
|
||||||
@@ -198,6 +201,7 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb])
|
|
||||||
error (0, 0, _("Must specify user name for stat-user option"));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
+ free ((char *) stat_user);
|
|
||||||
stat_user = xstrdup (arg1);
|
|
||||||
|
|
||||||
struct passwd *pw = getpwnam (stat_user);
|
|
@ -1,306 +0,0 @@
|
|||||||
commit 2f498f3d140ab5152bd784df2be7af7d9c5e63ed
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Tue Aug 14 10:57:48 2018 +0200
|
|
||||||
|
|
||||||
nss_files: Fix file stream leak in aliases lookup [BZ #23521]
|
|
||||||
|
|
||||||
In order to get a clean test case, it was necessary to fix partially
|
|
||||||
fixed bug 23522 as well.
|
|
||||||
|
|
||||||
(cherry picked from commit e95c6f61920a0f9237cfb292fa44ad500e1df09b)
|
|
||||||
|
|
||||||
diff --git a/nss/Makefile b/nss/Makefile
|
|
||||||
index 66fac7f5b8a4c0d8..5209fc0456dd6786 100644
|
|
||||||
--- a/nss/Makefile
|
|
||||||
+++ b/nss/Makefile
|
|
||||||
@@ -65,6 +65,7 @@ ifeq (yes,$(build-shared))
|
|
||||||
tests += tst-nss-files-hosts-erange
|
|
||||||
tests += tst-nss-files-hosts-multi
|
|
||||||
tests += tst-nss-files-hosts-getent
|
|
||||||
+tests += tst-nss-files-alias-leak
|
|
||||||
endif
|
|
||||||
|
|
||||||
# If we have a thread library then we can test cancellation against
|
|
||||||
@@ -171,3 +172,5 @@ endif
|
|
||||||
$(objpfx)tst-nss-files-hosts-erange: $(libdl)
|
|
||||||
$(objpfx)tst-nss-files-hosts-multi: $(libdl)
|
|
||||||
$(objpfx)tst-nss-files-hosts-getent: $(libdl)
|
|
||||||
+$(objpfx)tst-nss-files-alias-leak: $(libdl)
|
|
||||||
+$(objpfx)tst-nss-files-alias-leak.out: $(objpfx)/libnss_files.so
|
|
||||||
diff --git a/nss/nss_files/files-alias.c b/nss/nss_files/files-alias.c
|
|
||||||
index cfd34b66b921bbff..35b0bfc5d2479ab6 100644
|
|
||||||
--- a/nss/nss_files/files-alias.c
|
|
||||||
+++ b/nss/nss_files/files-alias.c
|
|
||||||
@@ -221,6 +221,13 @@ get_next_alias (FILE *stream, const char *match, struct aliasent *result,
|
|
||||||
{
|
|
||||||
while (! feof_unlocked (listfile))
|
|
||||||
{
|
|
||||||
+ if (room_left < 2)
|
|
||||||
+ {
|
|
||||||
+ free (old_line);
|
|
||||||
+ fclose (listfile);
|
|
||||||
+ goto no_more_room;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
first_unused[room_left - 1] = '\xff';
|
|
||||||
line = fgets_unlocked (first_unused, room_left,
|
|
||||||
listfile);
|
|
||||||
@@ -229,6 +236,7 @@ get_next_alias (FILE *stream, const char *match, struct aliasent *result,
|
|
||||||
if (first_unused[room_left - 1] != '\xff')
|
|
||||||
{
|
|
||||||
free (old_line);
|
|
||||||
+ fclose (listfile);
|
|
||||||
goto no_more_room;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -256,6 +264,7 @@ get_next_alias (FILE *stream, const char *match, struct aliasent *result,
|
|
||||||
+ __alignof__ (char *)))
|
|
||||||
{
|
|
||||||
free (old_line);
|
|
||||||
+ fclose (listfile);
|
|
||||||
goto no_more_room;
|
|
||||||
}
|
|
||||||
room_left -= ((first_unused - cp)
|
|
||||||
diff --git a/nss/tst-nss-files-alias-leak.c b/nss/tst-nss-files-alias-leak.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000..26d38e2dba1ddaf3
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/nss/tst-nss-files-alias-leak.c
|
|
||||||
@@ -0,0 +1,237 @@
|
|
||||||
+/* Check for file descriptor leak in alias :include: processing (bug 23521).
|
|
||||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <http://www.gnu.org/licenses/>. */
|
|
||||||
+
|
|
||||||
+#include <aliases.h>
|
|
||||||
+#include <array_length.h>
|
|
||||||
+#include <dlfcn.h>
|
|
||||||
+#include <errno.h>
|
|
||||||
+#include <gnu/lib-names.h>
|
|
||||||
+#include <nss.h>
|
|
||||||
+#include <stdlib.h>
|
|
||||||
+#include <string.h>
|
|
||||||
+#include <support/check.h>
|
|
||||||
+#include <support/namespace.h>
|
|
||||||
+#include <support/support.h>
|
|
||||||
+#include <support/temp_file.h>
|
|
||||||
+#include <support/test-driver.h>
|
|
||||||
+#include <support/xstdio.h>
|
|
||||||
+#include <support/xunistd.h>
|
|
||||||
+
|
|
||||||
+static struct support_chroot *chroot_env;
|
|
||||||
+
|
|
||||||
+/* Number of the aliases for the "many" user. This must be large
|
|
||||||
+ enough to trigger reallocation for the pointer array, but result in
|
|
||||||
+ answers below the maximum size tried in do_test. */
|
|
||||||
+enum { many_aliases = 30 };
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+prepare (int argc, char **argv)
|
|
||||||
+{
|
|
||||||
+ chroot_env = support_chroot_create
|
|
||||||
+ ((struct support_chroot_configuration) { } );
|
|
||||||
+
|
|
||||||
+ char *path = xasprintf ("%s/etc/aliases", chroot_env->path_chroot);
|
|
||||||
+ add_temp_file (path);
|
|
||||||
+ support_write_file_string
|
|
||||||
+ (path,
|
|
||||||
+ "user1: :include:/etc/aliases.user1\n"
|
|
||||||
+ "user2: :include:/etc/aliases.user2\n"
|
|
||||||
+ "comment: comment1, :include:/etc/aliases.comment\n"
|
|
||||||
+ "many: :include:/etc/aliases.many\n");
|
|
||||||
+ free (path);
|
|
||||||
+
|
|
||||||
+ path = xasprintf ("%s/etc/aliases.user1", chroot_env->path_chroot);
|
|
||||||
+ add_temp_file (path);
|
|
||||||
+ support_write_file_string (path, "alias1\n");
|
|
||||||
+ free (path);
|
|
||||||
+
|
|
||||||
+ path = xasprintf ("%s/etc/aliases.user2", chroot_env->path_chroot);
|
|
||||||
+ add_temp_file (path);
|
|
||||||
+ support_write_file_string (path, "alias1a, alias2\n");
|
|
||||||
+ free (path);
|
|
||||||
+
|
|
||||||
+ path = xasprintf ("%s/etc/aliases.comment", chroot_env->path_chroot);
|
|
||||||
+ add_temp_file (path);
|
|
||||||
+ support_write_file_string
|
|
||||||
+ (path,
|
|
||||||
+ /* The line must be longer than the line with the :include:
|
|
||||||
+ directive in /etc/aliases. */
|
|
||||||
+ "# Long line. ##############################################\n"
|
|
||||||
+ "comment2\n");
|
|
||||||
+ free (path);
|
|
||||||
+
|
|
||||||
+ path = xasprintf ("%s/etc/aliases.many", chroot_env->path_chroot);
|
|
||||||
+ add_temp_file (path);
|
|
||||||
+ FILE *fp = xfopen (path, "w");
|
|
||||||
+ for (int i = 0; i < many_aliases; ++i)
|
|
||||||
+ fprintf (fp, "a%d\n", i);
|
|
||||||
+ TEST_VERIFY_EXIT (! ferror (fp));
|
|
||||||
+ xfclose (fp);
|
|
||||||
+ free (path);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* The names of the users to test. */
|
|
||||||
+static const char *users[] = { "user1", "user2", "comment", "many" };
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+check_aliases (int id, const struct aliasent *e)
|
|
||||||
+{
|
|
||||||
+ TEST_VERIFY_EXIT (id >= 0 || id < array_length (users));
|
|
||||||
+ const char *name = users[id];
|
|
||||||
+ TEST_COMPARE_BLOB (e->alias_name, strlen (e->alias_name),
|
|
||||||
+ name, strlen (name));
|
|
||||||
+
|
|
||||||
+ switch (id)
|
|
||||||
+ {
|
|
||||||
+ case 0:
|
|
||||||
+ TEST_COMPARE (e->alias_members_len, 1);
|
|
||||||
+ TEST_COMPARE_BLOB (e->alias_members[0], strlen (e->alias_members[0]),
|
|
||||||
+ "alias1", strlen ("alias1"));
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case 1:
|
|
||||||
+ TEST_COMPARE (e->alias_members_len, 2);
|
|
||||||
+ TEST_COMPARE_BLOB (e->alias_members[0], strlen (e->alias_members[0]),
|
|
||||||
+ "alias1a", strlen ("alias1a"));
|
|
||||||
+ TEST_COMPARE_BLOB (e->alias_members[1], strlen (e->alias_members[1]),
|
|
||||||
+ "alias2", strlen ("alias2"));
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case 2:
|
|
||||||
+ TEST_COMPARE (e->alias_members_len, 2);
|
|
||||||
+ TEST_COMPARE_BLOB (e->alias_members[0], strlen (e->alias_members[0]),
|
|
||||||
+ "comment1", strlen ("comment1"));
|
|
||||||
+ TEST_COMPARE_BLOB (e->alias_members[1], strlen (e->alias_members[1]),
|
|
||||||
+ "comment2", strlen ("comment2"));
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case 3:
|
|
||||||
+ TEST_COMPARE (e->alias_members_len, many_aliases);
|
|
||||||
+ for (int i = 0; i < e->alias_members_len; ++i)
|
|
||||||
+ {
|
|
||||||
+ char alias[30];
|
|
||||||
+ int len = snprintf (alias, sizeof (alias), "a%d", i);
|
|
||||||
+ TEST_VERIFY_EXIT (len > 0);
|
|
||||||
+ TEST_COMPARE_BLOB (e->alias_members[i], strlen (e->alias_members[i]),
|
|
||||||
+ alias, len);
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+do_test (void)
|
|
||||||
+{
|
|
||||||
+ /* Make sure we don't try to load the module in the chroot. */
|
|
||||||
+ if (dlopen (LIBNSS_FILES_SO, RTLD_NOW) == NULL)
|
|
||||||
+ FAIL_EXIT1 ("could not load " LIBNSS_FILES_SO ": %s", dlerror ());
|
|
||||||
+
|
|
||||||
+ /* Some of these descriptors will become unavailable if there is a
|
|
||||||
+ file descriptor leak. 10 is chosen somewhat arbitrarily. The
|
|
||||||
+ array must be longer than the number of files opened by nss_files
|
|
||||||
+ at the same time (currently that number is 2). */
|
|
||||||
+ int next_descriptors[10];
|
|
||||||
+ for (size_t i = 0; i < array_length (next_descriptors); ++i)
|
|
||||||
+ {
|
|
||||||
+ next_descriptors[i] = dup (0);
|
|
||||||
+ TEST_VERIFY_EXIT (next_descriptors[i] > 0);
|
|
||||||
+ }
|
|
||||||
+ for (size_t i = 0; i < array_length (next_descriptors); ++i)
|
|
||||||
+ xclose (next_descriptors[i]);
|
|
||||||
+
|
|
||||||
+ support_become_root ();
|
|
||||||
+ if (!support_can_chroot ())
|
|
||||||
+ return EXIT_UNSUPPORTED;
|
|
||||||
+
|
|
||||||
+ __nss_configure_lookup ("aliases", "files");
|
|
||||||
+
|
|
||||||
+ xchroot (chroot_env->path_chroot);
|
|
||||||
+
|
|
||||||
+ /* Attempt various buffer sizes. If the operation succeeds, we
|
|
||||||
+ expect correct data. */
|
|
||||||
+ for (int id = 0; id < array_length (users); ++id)
|
|
||||||
+ {
|
|
||||||
+ bool found = false;
|
|
||||||
+ for (size_t size = 1; size <= 1000; ++size)
|
|
||||||
+ {
|
|
||||||
+ void *buffer = malloc (size);
|
|
||||||
+ struct aliasent result;
|
|
||||||
+ struct aliasent *res;
|
|
||||||
+ errno = EINVAL;
|
|
||||||
+ int ret = getaliasbyname_r (users[id], &result, buffer, size, &res);
|
|
||||||
+ if (ret == 0)
|
|
||||||
+ {
|
|
||||||
+ if (res != NULL)
|
|
||||||
+ {
|
|
||||||
+ found = true;
|
|
||||||
+ check_aliases (id, res);
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ {
|
|
||||||
+ support_record_failure ();
|
|
||||||
+ printf ("error: failed lookup for user \"%s\", size %zu\n",
|
|
||||||
+ users[id], size);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ else if (ret != ERANGE)
|
|
||||||
+ {
|
|
||||||
+ support_record_failure ();
|
|
||||||
+ printf ("error: invalid return code %d (user \%s\", size %zu)\n",
|
|
||||||
+ ret, users[id], size);
|
|
||||||
+ }
|
|
||||||
+ free (buffer);
|
|
||||||
+
|
|
||||||
+ /* Make sure that we did not have a file descriptor leak. */
|
|
||||||
+ for (size_t i = 0; i < array_length (next_descriptors); ++i)
|
|
||||||
+ {
|
|
||||||
+ int new_fd = dup (0);
|
|
||||||
+ if (new_fd != next_descriptors[i])
|
|
||||||
+ {
|
|
||||||
+ support_record_failure ();
|
|
||||||
+ printf ("error: descriptor %d at index %zu leaked"
|
|
||||||
+ " (user \"%s\", size %zu)\n",
|
|
||||||
+ next_descriptors[i], i, users[id], size);
|
|
||||||
+
|
|
||||||
+ /* Close unexpected descriptor, the leak probing
|
|
||||||
+ descriptors, and the leaked descriptor
|
|
||||||
+ next_descriptors[i]. */
|
|
||||||
+ xclose (new_fd);
|
|
||||||
+ for (size_t j = 0; j <= i; ++j)
|
|
||||||
+ xclose (next_descriptors[j]);
|
|
||||||
+ goto next_size;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ for (size_t i = 0; i < array_length (next_descriptors); ++i)
|
|
||||||
+ xclose (next_descriptors[i]);
|
|
||||||
+
|
|
||||||
+ next_size:
|
|
||||||
+ ;
|
|
||||||
+ }
|
|
||||||
+ if (!found)
|
|
||||||
+ {
|
|
||||||
+ support_record_failure ();
|
|
||||||
+ printf ("error: user %s not found\n", users[id]);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ support_chroot_free (chroot_env);
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#define PREPARE prepare
|
|
||||||
+#include <support/test-driver.c>
|
|
@ -1,27 +0,0 @@
|
|||||||
commit aa8a3e4cdef20c50cb20f008864fff05cbfbdf29
|
|
||||||
Author: Martin Kuchta <martin.kuchta@netapp.com>
|
|
||||||
Date: Mon Aug 27 18:54:46 2018 +0200
|
|
||||||
|
|
||||||
pthread_cond_broadcast: Fix waiters-after-spinning case [BZ #23538]
|
|
||||||
|
|
||||||
(cherry picked from commit 99ea93ca31795469d2a1f1570f17a5c39c2eb7e2)
|
|
||||||
|
|
||||||
diff --git a/nptl/pthread_cond_common.c b/nptl/pthread_cond_common.c
|
|
||||||
index 8e425eb01eceabec..479e54febb417675 100644
|
|
||||||
--- a/nptl/pthread_cond_common.c
|
|
||||||
+++ b/nptl/pthread_cond_common.c
|
|
||||||
@@ -405,8 +405,12 @@ __condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
|
||||||
{
|
|
||||||
/* There is still a waiter after spinning. Set the wake-request
|
|
||||||
flag and block. Relaxed MO is fine because this is just about
|
|
||||||
- this futex word. */
|
|
||||||
- r = atomic_fetch_or_relaxed (cond->__data.__g_refs + g1, 1);
|
|
||||||
+ this futex word.
|
|
||||||
+
|
|
||||||
+ Update r to include the set wake-request flag so that the upcoming
|
|
||||||
+ futex_wait only blocks if the flag is still set (otherwise, we'd
|
|
||||||
+ violate the basic client-side futex protocol). */
|
|
||||||
+ r = atomic_fetch_or_relaxed (cond->__data.__g_refs + g1, 1) | 1;
|
|
||||||
|
|
||||||
if ((r >> 1) > 0)
|
|
||||||
futex_wait_simple (cond->__data.__g_refs + g1, r, private);
|
|
@ -1,41 +0,0 @@
|
|||||||
commit 58559f14437d2aa71753a29fed435efa06aa4576
|
|
||||||
Author: Paul Eggert <eggert@cs.ucla.edu>
|
|
||||||
Date: Tue Aug 28 21:54:28 2018 +0200
|
|
||||||
|
|
||||||
regex: fix uninitialized memory access
|
|
||||||
|
|
||||||
I introduced this bug into gnulib in commit
|
|
||||||
8335a4d6c7b4448cd0bcb6d0bebf1d456bcfdb17 dated 2006-04-10;
|
|
||||||
eventually it was merged into glibc. The bug was found by
|
|
||||||
project-repo <bugs@feusi.co> and reported here:
|
|
||||||
https://lists.gnu.org/r/sed-devel/2018-08/msg00017.html
|
|
||||||
Diagnosis and draft fix reported by Assaf Gordon here:
|
|
||||||
https://lists.gnu.org/r/bug-gnulib/2018-08/msg00071.html
|
|
||||||
https://lists.gnu.org/r/bug-gnulib/2018-08/msg00142.html
|
|
||||||
* posix/regex_internal.c (build_wcs_upper_buffer):
|
|
||||||
Fix bug when mbrtowc returns 0.
|
|
||||||
|
|
||||||
(cherry picked from commit bc680b336971305cb39896b30d72dc7101b62242)
|
|
||||||
|
|
||||||
diff --git a/posix/regex_internal.c b/posix/regex_internal.c
|
|
||||||
index 7f0083b918de6530..b10588f1ccbb1992 100644
|
|
||||||
--- a/posix/regex_internal.c
|
|
||||||
+++ b/posix/regex_internal.c
|
|
||||||
@@ -317,7 +317,7 @@ build_wcs_upper_buffer (re_string_t *pstr)
|
|
||||||
mbclen = __mbrtowc (&wc,
|
|
||||||
((const char *) pstr->raw_mbs + pstr->raw_mbs_idx
|
|
||||||
+ byte_idx), remain_len, &pstr->cur_state);
|
|
||||||
- if (BE (mbclen < (size_t) -2, 1))
|
|
||||||
+ if (BE (0 < mbclen && mbclen < (size_t) -2, 1))
|
|
||||||
{
|
|
||||||
wchar_t wcu = __towupper (wc);
|
|
||||||
if (wcu != wc)
|
|
||||||
@@ -386,7 +386,7 @@ build_wcs_upper_buffer (re_string_t *pstr)
|
|
||||||
else
|
|
||||||
p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx;
|
|
||||||
mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state);
|
|
||||||
- if (BE (mbclen < (size_t) -2, 1))
|
|
||||||
+ if (BE (0 < mbclen && mbclen < (size_t) -2, 1))
|
|
||||||
{
|
|
||||||
wchar_t wcu = __towupper (wc);
|
|
||||||
if (wcu != wc)
|
|
@ -1,226 +0,0 @@
|
|||||||
commit 0b79004569e5ce1669136b8c41564c3809730f15
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Tue Aug 28 12:57:46 2018 +0200
|
|
||||||
|
|
||||||
regex: Add test tst-regcomp-truncated [BZ #23578]
|
|
||||||
|
|
||||||
(cherry picked from commit 761404b74d9853ce1608195e24f25b78a910591a)
|
|
||||||
|
|
||||||
diff --git a/posix/Makefile b/posix/Makefile
|
|
||||||
index 00c62841a282f15a..83162123f9c927a0 100644
|
|
||||||
--- a/posix/Makefile
|
|
||||||
+++ b/posix/Makefile
|
|
||||||
@@ -96,7 +96,7 @@ tests := test-errno tstgetopt testfnm runtests runptests \
|
|
||||||
tst-posix_fadvise tst-posix_fadvise64 \
|
|
||||||
tst-sysconf-empty-chroot tst-glob_symlinks tst-fexecve \
|
|
||||||
tst-glob-tilde test-ssize-max tst-spawn4 bug-regex37 \
|
|
||||||
- bug-regex38
|
|
||||||
+ bug-regex38 tst-regcomp-truncated
|
|
||||||
tests-internal := bug-regex5 bug-regex20 bug-regex33 \
|
|
||||||
tst-rfc3484 tst-rfc3484-2 tst-rfc3484-3 \
|
|
||||||
tst-glob_lstat_compat tst-spawn4-compat
|
|
||||||
@@ -194,6 +194,7 @@ $(objpfx)tst-regex2.out: $(gen-locales)
|
|
||||||
$(objpfx)tst-regexloc.out: $(gen-locales)
|
|
||||||
$(objpfx)tst-rxspencer.out: $(gen-locales)
|
|
||||||
$(objpfx)tst-rxspencer-no-utf8.out: $(gen-locales)
|
|
||||||
+$(objpfx)tst-regcomp-truncated.out: $(gen-locales)
|
|
||||||
endif
|
|
||||||
|
|
||||||
# If we will use the generic uname implementation, we must figure out what
|
|
||||||
diff --git a/posix/tst-regcomp-truncated.c b/posix/tst-regcomp-truncated.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000..a4a1581bbc2b39eb
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/posix/tst-regcomp-truncated.c
|
|
||||||
@@ -0,0 +1,191 @@
|
|
||||||
+/* Test compilation of truncated regular expressions.
|
|
||||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <http://www.gnu.org/licenses/>. */
|
|
||||||
+
|
|
||||||
+/* This test constructs various patterns in an attempt to trigger
|
|
||||||
+ over-reading the regular expression compiler, such as bug
|
|
||||||
+ 23578. */
|
|
||||||
+
|
|
||||||
+#include <array_length.h>
|
|
||||||
+#include <errno.h>
|
|
||||||
+#include <locale.h>
|
|
||||||
+#include <regex.h>
|
|
||||||
+#include <stdio.h>
|
|
||||||
+#include <stdlib.h>
|
|
||||||
+#include <string.h>
|
|
||||||
+#include <support/check.h>
|
|
||||||
+#include <support/next_to_fault.h>
|
|
||||||
+#include <support/support.h>
|
|
||||||
+#include <support/test-driver.h>
|
|
||||||
+#include <wchar.h>
|
|
||||||
+
|
|
||||||
+/* Locales to test. */
|
|
||||||
+static const char locales[][17] =
|
|
||||||
+ {
|
|
||||||
+ "C",
|
|
||||||
+ "en_US.UTF-8",
|
|
||||||
+ "de_DE.ISO-8859-1",
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+/* Syntax options. Will be combined with other flags. */
|
|
||||||
+static const reg_syntax_t syntaxes[] =
|
|
||||||
+ {
|
|
||||||
+ RE_SYNTAX_EMACS,
|
|
||||||
+ RE_SYNTAX_AWK,
|
|
||||||
+ RE_SYNTAX_GNU_AWK,
|
|
||||||
+ RE_SYNTAX_POSIX_AWK,
|
|
||||||
+ RE_SYNTAX_GREP,
|
|
||||||
+ RE_SYNTAX_EGREP,
|
|
||||||
+ RE_SYNTAX_POSIX_EGREP,
|
|
||||||
+ RE_SYNTAX_POSIX_BASIC,
|
|
||||||
+ RE_SYNTAX_POSIX_EXTENDED,
|
|
||||||
+ RE_SYNTAX_POSIX_MINIMAL_EXTENDED,
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+/* Trailing characters placed after the initial character. */
|
|
||||||
+static const char trailing_strings[][4] =
|
|
||||||
+ {
|
|
||||||
+ "",
|
|
||||||
+ "[",
|
|
||||||
+ "\\",
|
|
||||||
+ "[\\",
|
|
||||||
+ "(",
|
|
||||||
+ "(\\",
|
|
||||||
+ "\\(",
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+do_test (void)
|
|
||||||
+{
|
|
||||||
+ /* Staging buffer for the constructed regular expression. */
|
|
||||||
+ char buffer[16];
|
|
||||||
+
|
|
||||||
+ /* Allocation used to detect over-reading by the regular expression
|
|
||||||
+ compiler. */
|
|
||||||
+ struct support_next_to_fault ntf
|
|
||||||
+ = support_next_to_fault_allocate (sizeof (buffer));
|
|
||||||
+
|
|
||||||
+ /* Arbitrary Unicode codepoint at which we stop generating
|
|
||||||
+ characters. We do not probe the whole range because that would
|
|
||||||
+ take too long due to combinatorical exploision as the result of
|
|
||||||
+ combination with other flags. */
|
|
||||||
+ static const wchar_t last_character = 0xfff;
|
|
||||||
+
|
|
||||||
+ for (size_t locale_idx = 0; locale_idx < array_length (locales);
|
|
||||||
+ ++ locale_idx)
|
|
||||||
+ {
|
|
||||||
+ if (setlocale (LC_ALL, locales[locale_idx]) == NULL)
|
|
||||||
+ {
|
|
||||||
+ support_record_failure ();
|
|
||||||
+ printf ("error: setlocale (\"%s\"): %m", locales[locale_idx]);
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+ if (test_verbose > 0)
|
|
||||||
+ printf ("info: testing locale \"%s\"\n", locales[locale_idx]);
|
|
||||||
+
|
|
||||||
+ for (wchar_t wc = 0; wc <= last_character; ++wc)
|
|
||||||
+ {
|
|
||||||
+ char *after_wc;
|
|
||||||
+ if (wc == 0)
|
|
||||||
+ {
|
|
||||||
+ /* wcrtomb treats L'\0' in a special way. */
|
|
||||||
+ *buffer = '\0';
|
|
||||||
+ after_wc = &buffer[1];
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ {
|
|
||||||
+ mbstate_t ps = { };
|
|
||||||
+ size_t ret = wcrtomb (buffer, wc, &ps);
|
|
||||||
+ if (ret == (size_t) -1)
|
|
||||||
+ {
|
|
||||||
+ /* EILSEQ means that the target character set
|
|
||||||
+ cannot encode the character. */
|
|
||||||
+ if (errno != EILSEQ)
|
|
||||||
+ {
|
|
||||||
+ support_record_failure ();
|
|
||||||
+ printf ("error: wcrtomb (0x%x) failed: %m\n",
|
|
||||||
+ (unsigned) wc);
|
|
||||||
+ }
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+ TEST_VERIFY_EXIT (ret != 0);
|
|
||||||
+ after_wc = &buffer[ret];
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ for (size_t trailing_idx = 0;
|
|
||||||
+ trailing_idx < array_length (trailing_strings);
|
|
||||||
+ ++trailing_idx)
|
|
||||||
+ {
|
|
||||||
+ char *after_trailing
|
|
||||||
+ = stpcpy (after_wc, trailing_strings[trailing_idx]);
|
|
||||||
+
|
|
||||||
+ for (int do_nul = 0; do_nul < 2; ++do_nul)
|
|
||||||
+ {
|
|
||||||
+ char *after_nul;
|
|
||||||
+ if (do_nul)
|
|
||||||
+ {
|
|
||||||
+ *after_trailing = '\0';
|
|
||||||
+ after_nul = &after_trailing[1];
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ after_nul = after_trailing;
|
|
||||||
+
|
|
||||||
+ size_t length = after_nul - buffer;
|
|
||||||
+
|
|
||||||
+ /* Make sure that the faulting region starts
|
|
||||||
+ after the used portion of the buffer. */
|
|
||||||
+ char *ntf_start = ntf.buffer + sizeof (buffer) - length;
|
|
||||||
+ memcpy (ntf_start, buffer, length);
|
|
||||||
+
|
|
||||||
+ for (const reg_syntax_t *psyntax = syntaxes;
|
|
||||||
+ psyntax < array_end (syntaxes); ++psyntax)
|
|
||||||
+ for (int do_icase = 0; do_icase < 2; ++do_icase)
|
|
||||||
+ {
|
|
||||||
+ re_syntax_options = *psyntax;
|
|
||||||
+ if (do_icase)
|
|
||||||
+ re_syntax_options |= RE_ICASE;
|
|
||||||
+
|
|
||||||
+ regex_t reg;
|
|
||||||
+ memset (®, 0, sizeof (reg));
|
|
||||||
+ const char *msg = re_compile_pattern
|
|
||||||
+ (ntf_start, length, ®);
|
|
||||||
+ if (msg != NULL)
|
|
||||||
+ {
|
|
||||||
+ if (test_verbose > 0)
|
|
||||||
+ {
|
|
||||||
+ char *quoted = support_quote_blob
|
|
||||||
+ (buffer, length);
|
|
||||||
+ printf ("info: compilation failed for pattern"
|
|
||||||
+ " \"%s\", syntax 0x%lx: %s\n",
|
|
||||||
+ quoted, re_syntax_options, msg);
|
|
||||||
+ free (quoted);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ regfree (®);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ support_next_to_fault_free (&ntf);
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#include <support/test-driver.c>
|
|
@ -1,34 +0,0 @@
|
|||||||
commit 3a67c72c1512f778304a5644dea2fcf5bdece274
|
|
||||||
Author: Andreas Schwab <schwab@suse.de>
|
|
||||||
Date: Thu Sep 27 12:37:06 2018 +0200
|
|
||||||
|
|
||||||
Fix stack overflow in tst-setcontext9 (bug 23717)
|
|
||||||
|
|
||||||
The function f1a, executed on a stack of size 32k, allocates an object of
|
|
||||||
size 32k on the stack. Make the stack variables static to reduce
|
|
||||||
excessive stack usage.
|
|
||||||
|
|
||||||
(cherry picked from commit f841c97e515a1673485a2b12b3c280073d737890)
|
|
||||||
|
|
||||||
diff --git a/stdlib/tst-setcontext9.c b/stdlib/tst-setcontext9.c
|
|
||||||
index db8355766ca7b906..009928235dd5987e 100644
|
|
||||||
--- a/stdlib/tst-setcontext9.c
|
|
||||||
+++ b/stdlib/tst-setcontext9.c
|
|
||||||
@@ -58,7 +58,7 @@ f1b (void)
|
|
||||||
static void
|
|
||||||
f1a (void)
|
|
||||||
{
|
|
||||||
- char st2[32768];
|
|
||||||
+ static char st2[32768];
|
|
||||||
puts ("start f1a");
|
|
||||||
if (getcontext (&ctx[2]) != 0)
|
|
||||||
{
|
|
||||||
@@ -93,7 +93,7 @@ f1a (void)
|
|
||||||
static int
|
|
||||||
do_test (void)
|
|
||||||
{
|
|
||||||
- char st1[32768];
|
|
||||||
+ static char st1[32768];
|
|
||||||
puts ("making contexts");
|
|
||||||
if (getcontext (&ctx[0]) != 0)
|
|
||||||
{
|
|
@ -1,100 +0,0 @@
|
|||||||
commit a55e109709af55e6ed67d3f9536cac5d929c982e
|
|
||||||
Author: Carlos O'Donell <carlos@redhat.com>
|
|
||||||
Date: Wed Sep 5 01:16:42 2018 -0400
|
|
||||||
|
|
||||||
Fix tst-setcontext9 for optimized small stacks.
|
|
||||||
|
|
||||||
If the compiler reduces the stack usage in function f1 before calling
|
|
||||||
into function f2, then when we swapcontext back to f1 and continue
|
|
||||||
execution we may overwrite registers that were spilled to the stack
|
|
||||||
while f2 was executing. Later when we return to f2 the corrupt
|
|
||||||
registers will be reloaded from the stack and the test will crash. This
|
|
||||||
was most commonly observed on i686 with __x86.get_pc_thunk.dx and
|
|
||||||
needing to save and restore $edx. Overall i686 has few registers and
|
|
||||||
the spilling to the stack is bound to happen, therefore the solution to
|
|
||||||
making this test robust is to split function f1 into two parts f1a and
|
|
||||||
f1b, and allocate f1b it's own stack such that subsequent execution does
|
|
||||||
not overwrite the stack in use by function f2.
|
|
||||||
|
|
||||||
Tested on i686 and x86_64.
|
|
||||||
|
|
||||||
Signed-off-by: Carlos O'Donell <carlos@redhat.com>
|
|
||||||
(cherry picked from commit 791b350dc725545e3f9b5db0f97ebdbc60c9735f)
|
|
||||||
|
|
||||||
diff --git a/stdlib/tst-setcontext9.c b/stdlib/tst-setcontext9.c
|
|
||||||
index 4636ce9030fa38a7..db8355766ca7b906 100644
|
|
||||||
--- a/stdlib/tst-setcontext9.c
|
|
||||||
+++ b/stdlib/tst-setcontext9.c
|
|
||||||
@@ -41,26 +41,55 @@ f2 (void)
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
-f1 (void)
|
|
||||||
+f1b (void)
|
|
||||||
{
|
|
||||||
- puts ("start f1");
|
|
||||||
- if (getcontext (&ctx[2]) != 0)
|
|
||||||
- {
|
|
||||||
- printf ("%s: getcontext: %m\n", __FUNCTION__);
|
|
||||||
- exit (EXIT_FAILURE);
|
|
||||||
- }
|
|
||||||
if (done)
|
|
||||||
{
|
|
||||||
- puts ("set context in f1");
|
|
||||||
+ puts ("set context in f1b");
|
|
||||||
if (setcontext (&ctx[3]) != 0)
|
|
||||||
{
|
|
||||||
printf ("%s: setcontext: %m\n", __FUNCTION__);
|
|
||||||
exit (EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+ exit (EXIT_FAILURE);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+f1a (void)
|
|
||||||
+{
|
|
||||||
+ char st2[32768];
|
|
||||||
+ puts ("start f1a");
|
|
||||||
+ if (getcontext (&ctx[2]) != 0)
|
|
||||||
+ {
|
|
||||||
+ printf ("%s: getcontext: %m\n", __FUNCTION__);
|
|
||||||
+ exit (EXIT_FAILURE);
|
|
||||||
+ }
|
|
||||||
+ ctx[2].uc_stack.ss_sp = st2;
|
|
||||||
+ ctx[2].uc_stack.ss_size = sizeof st2;
|
|
||||||
+ ctx[2].uc_link = &ctx[0];
|
|
||||||
+ makecontext (&ctx[2], (void (*) (void)) f1b, 0);
|
|
||||||
f2 ();
|
|
||||||
}
|
|
||||||
|
|
||||||
+/* The execution path through the test looks like this:
|
|
||||||
+ do_test (call)
|
|
||||||
+ -> "making contexts"
|
|
||||||
+ -> "swap contexts"
|
|
||||||
+ f1a (via swapcontext to ctx[1], with alternate stack)
|
|
||||||
+ -> "start f1a"
|
|
||||||
+ f2 (call)
|
|
||||||
+ -> "swap contexts in f2"
|
|
||||||
+ f1b (via swapcontext to ctx[2], with alternate stack)
|
|
||||||
+ -> "set context in f1b"
|
|
||||||
+ do_test (via setcontext to ctx[3], main stack)
|
|
||||||
+ -> "setcontext"
|
|
||||||
+ f2 (via setcontext to ctx[4], with alternate stack)
|
|
||||||
+ -> "end f2"
|
|
||||||
+
|
|
||||||
+ We must use an alternate stack for f1b, because if we don't then the
|
|
||||||
+ result of executing an earlier caller may overwrite registers
|
|
||||||
+ spilled to the stack in f2. */
|
|
||||||
static int
|
|
||||||
do_test (void)
|
|
||||||
{
|
|
||||||
@@ -79,7 +108,7 @@ do_test (void)
|
|
||||||
ctx[1].uc_stack.ss_sp = st1;
|
|
||||||
ctx[1].uc_stack.ss_size = sizeof st1;
|
|
||||||
ctx[1].uc_link = &ctx[0];
|
|
||||||
- makecontext (&ctx[1], (void (*) (void)) f1, 0);
|
|
||||||
+ makecontext (&ctx[1], (void (*) (void)) f1a, 0);
|
|
||||||
puts ("swap contexts");
|
|
||||||
if (swapcontext (&ctx[3], &ctx[1]) != 0)
|
|
||||||
{
|
|
@ -1,61 +0,0 @@
|
|||||||
commit b297581acb66f80b513996c1580158b0fb12d469
|
|
||||||
Author: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
|
|
||||||
Date: Mon Jan 14 17:54:44 2019 -0200
|
|
||||||
|
|
||||||
Add XFAIL_ROUNDING_IBM128_LIBGCC to more fma() tests
|
|
||||||
|
|
||||||
Ignore 16 errors in math/test-ldouble-fma and 4 errors in
|
|
||||||
math/test-ildouble-fma when IBM 128-bit long double used.
|
|
||||||
These errors are caused by spurious overflows from libgcc.
|
|
||||||
|
|
||||||
* math/libm-test-fma.inc (fma_test_data): Set
|
|
||||||
XFAIL_ROUNDING_IBM128_LIBGCC to more tests.
|
|
||||||
|
|
||||||
Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
|
|
||||||
(cherry picked from commit ecdacd34a2ac3b6d5a529ff218b29261d9d98a7a)
|
|
||||||
|
|
||||||
diff --git a/math/libm-test-fma.inc b/math/libm-test-fma.inc
|
|
||||||
index 5b29fb820194e055..a7ee40992420c1ab 100644
|
|
||||||
--- a/math/libm-test-fma.inc
|
|
||||||
+++ b/math/libm-test-fma.inc
|
|
||||||
@@ -119,32 +119,32 @@ static const struct test_fff_f_data fma_test_data[] =
|
|
||||||
TEST_fff_f (fma, plus_infty, plus_infty, -min_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
TEST_fff_f (fma, plus_infty, plus_infty, min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
TEST_fff_f (fma, plus_infty, plus_infty, -min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
- TEST_fff_f (fma, plus_infty, plus_infty, max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
- TEST_fff_f (fma, plus_infty, plus_infty, -max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
+ TEST_fff_f (fma, plus_infty, plus_infty, max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
|
|
||||||
+ TEST_fff_f (fma, plus_infty, plus_infty, -max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
|
|
||||||
TEST_fff_f (fma, plus_infty, minus_infty, plus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
TEST_fff_f (fma, plus_infty, minus_infty, minus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
TEST_fff_f (fma, plus_infty, minus_infty, min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
TEST_fff_f (fma, plus_infty, minus_infty, -min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
TEST_fff_f (fma, plus_infty, minus_infty, min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
TEST_fff_f (fma, plus_infty, minus_infty, -min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
- TEST_fff_f (fma, plus_infty, minus_infty, max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
- TEST_fff_f (fma, plus_infty, minus_infty, -max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
+ TEST_fff_f (fma, plus_infty, minus_infty, max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
|
|
||||||
+ TEST_fff_f (fma, plus_infty, minus_infty, -max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
|
|
||||||
TEST_fff_f (fma, minus_infty, plus_infty, plus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
TEST_fff_f (fma, minus_infty, plus_infty, minus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
TEST_fff_f (fma, minus_infty, plus_infty, min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
TEST_fff_f (fma, minus_infty, plus_infty, -min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
TEST_fff_f (fma, minus_infty, plus_infty, min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
TEST_fff_f (fma, minus_infty, plus_infty, -min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
- TEST_fff_f (fma, minus_infty, plus_infty, max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
- TEST_fff_f (fma, minus_infty, plus_infty, -max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
+ TEST_fff_f (fma, minus_infty, plus_infty, max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
|
|
||||||
+ TEST_fff_f (fma, minus_infty, plus_infty, -max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
|
|
||||||
TEST_fff_f (fma, minus_infty, minus_infty, plus_zero, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
TEST_fff_f (fma, minus_infty, minus_infty, minus_zero, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
TEST_fff_f (fma, minus_infty, minus_infty, min_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
TEST_fff_f (fma, minus_infty, minus_infty, -min_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
TEST_fff_f (fma, minus_infty, minus_infty, min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
TEST_fff_f (fma, minus_infty, minus_infty, -min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
- TEST_fff_f (fma, minus_infty, minus_infty, max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
- TEST_fff_f (fma, minus_infty, minus_infty, -max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
|
||||||
+ TEST_fff_f (fma, minus_infty, minus_infty, max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
|
|
||||||
+ TEST_fff_f (fma, minus_infty, minus_infty, -max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
|
|
||||||
|
|
||||||
AUTO_TESTS_fff_f (fma),
|
|
||||||
};
|
|
@ -1,29 +0,0 @@
|
|||||||
commit e7d22db29cfdd2f1fb97a70a76fa53d151569945
|
|
||||||
Author: Mingli Yu <Mingli.Yu@windriver.com>
|
|
||||||
Date: Thu Sep 20 12:41:13 2018 +0200
|
|
||||||
|
|
||||||
Linux gethostid: Check for NULL value from gethostbyname_r [BZ #23679]
|
|
||||||
|
|
||||||
A NULL value can happen with certain gethostbyname_r failures.
|
|
||||||
|
|
||||||
(cherry picked from commit 1214ba06e6771acb953a190091b0f6055c64fd25)
|
|
||||||
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/gethostid.c b/sysdeps/unix/sysv/linux/gethostid.c
|
|
||||||
index 2e20f034dc134cc7..ee0190e7f945db1f 100644
|
|
||||||
--- a/sysdeps/unix/sysv/linux/gethostid.c
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/gethostid.c
|
|
||||||
@@ -102,12 +102,12 @@ gethostid (void)
|
|
||||||
{
|
|
||||||
int ret = __gethostbyname_r (hostname, &hostbuf,
|
|
||||||
tmpbuf.data, tmpbuf.length, &hp, &herr);
|
|
||||||
- if (ret == 0)
|
|
||||||
+ if (ret == 0 && hp != NULL)
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Enlarge the buffer on ERANGE. */
|
|
||||||
- if (herr == NETDB_INTERNAL && errno == ERANGE)
|
|
||||||
+ if (ret != 0 && herr == NETDB_INTERNAL && errno == ERANGE)
|
|
||||||
{
|
|
||||||
if (!scratch_buffer_grow (&tmpbuf))
|
|
||||||
return 0;
|
|
@ -1,146 +0,0 @@
|
|||||||
commit 307d04334d516bb180f484a2b283f97310bfee66
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Thu Sep 20 12:03:01 2018 +0200
|
|
||||||
|
|
||||||
misc: New test misc/tst-gethostid
|
|
||||||
|
|
||||||
The empty /etc/hosts file used to trigger bug 23679.
|
|
||||||
|
|
||||||
(cherry picked from commit db9a8ad4ff3fc58e3773a9a4d0cabe3c1bc9c94c)
|
|
||||||
|
|
||||||
diff --git a/misc/Makefile b/misc/Makefile
|
|
||||||
index b7be2bc19a6f7ed5..c9f81515ac9aef2c 100644
|
|
||||||
--- a/misc/Makefile
|
|
||||||
+++ b/misc/Makefile
|
|
||||||
@@ -86,6 +86,11 @@ tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \
|
|
||||||
tst-preadvwritev tst-preadvwritev64 tst-makedev tst-empty \
|
|
||||||
tst-preadvwritev2 tst-preadvwritev64v2
|
|
||||||
|
|
||||||
+# Tests which need libdl.
|
|
||||||
+ifeq (yes,$(build-shared))
|
|
||||||
+tests += tst-gethostid
|
|
||||||
+endif
|
|
||||||
+
|
|
||||||
tests-internal := tst-atomic tst-atomic-long tst-allocate_once
|
|
||||||
tests-static := tst-empty
|
|
||||||
|
|
||||||
@@ -145,3 +150,5 @@ tst-allocate_once-ENV = MALLOC_TRACE=$(objpfx)tst-allocate_once.mtrace
|
|
||||||
$(objpfx)tst-allocate_once-mem.out: $(objpfx)tst-allocate_once.out
|
|
||||||
$(common-objpfx)malloc/mtrace $(objpfx)tst-allocate_once.mtrace > $@; \
|
|
||||||
$(evaluate-test)
|
|
||||||
+
|
|
||||||
+$(objpfx)tst-gethostid: $(libdl)
|
|
||||||
diff --git a/misc/tst-gethostid.c b/misc/tst-gethostid.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000..1490aaf3f517ff1d
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/misc/tst-gethostid.c
|
|
||||||
@@ -0,0 +1,108 @@
|
|
||||||
+/* Basic test for gethostid.
|
|
||||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <http://www.gnu.org/licenses/>. */
|
|
||||||
+
|
|
||||||
+#include <gnu/lib-names.h>
|
|
||||||
+#include <nss.h>
|
|
||||||
+#include <stdio.h>
|
|
||||||
+#include <stdlib.h>
|
|
||||||
+#include <string.h>
|
|
||||||
+#include <support/namespace.h>
|
|
||||||
+#include <support/support.h>
|
|
||||||
+#include <support/temp_file.h>
|
|
||||||
+#include <support/xdlfcn.h>
|
|
||||||
+#include <support/xstdio.h>
|
|
||||||
+#include <support/xunistd.h>
|
|
||||||
+#include <unistd.h>
|
|
||||||
+
|
|
||||||
+/* Initial test is run outside a chroot, to increase the likelihood of
|
|
||||||
+ success. */
|
|
||||||
+static void
|
|
||||||
+outside_chroot (void *closure)
|
|
||||||
+{
|
|
||||||
+ long id = gethostid ();
|
|
||||||
+ printf ("info: host ID outside chroot: 0x%lx\n", id);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* The same, but this time perform a chroot operation. */
|
|
||||||
+static void
|
|
||||||
+in_chroot (void *closure)
|
|
||||||
+{
|
|
||||||
+ const char *chroot_path = closure;
|
|
||||||
+ xchroot (chroot_path);
|
|
||||||
+ long id = gethostid ();
|
|
||||||
+ printf ("info: host ID in chroot: 0x%lx\n", id);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+do_test (void)
|
|
||||||
+{
|
|
||||||
+ support_isolate_in_subprocess (outside_chroot, NULL);
|
|
||||||
+
|
|
||||||
+ /* Now run the test inside a chroot. */
|
|
||||||
+ support_become_root ();
|
|
||||||
+ if (!support_can_chroot ())
|
|
||||||
+ /* Cannot perform further tests. */
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ /* Only use nss_files. */
|
|
||||||
+ __nss_configure_lookup ("hosts", "files");
|
|
||||||
+
|
|
||||||
+ /* Load the DSO outside of the chroot. */
|
|
||||||
+ xdlopen (LIBNSS_FILES_SO, RTLD_LAZY);
|
|
||||||
+
|
|
||||||
+ char *chroot_dir = support_create_temp_directory ("tst-gethostid-");
|
|
||||||
+ support_isolate_in_subprocess (in_chroot, chroot_dir);
|
|
||||||
+
|
|
||||||
+ /* Tests with /etc/hosts in the chroot. */
|
|
||||||
+ {
|
|
||||||
+ char *path = xasprintf ("%s/etc", chroot_dir);
|
|
||||||
+ add_temp_file (path);
|
|
||||||
+ xmkdir (path, 0777);
|
|
||||||
+ free (path);
|
|
||||||
+ path = xasprintf ("%s/etc/hosts", chroot_dir);
|
|
||||||
+ add_temp_file (path);
|
|
||||||
+
|
|
||||||
+ FILE *fp = xfopen (path, "w");
|
|
||||||
+ xfclose (fp);
|
|
||||||
+ printf ("info: chroot test with an empty /etc/hosts file\n");
|
|
||||||
+ support_isolate_in_subprocess (in_chroot, chroot_dir);
|
|
||||||
+
|
|
||||||
+ char hostname[1024];
|
|
||||||
+ int ret = gethostname (hostname, sizeof (hostname));
|
|
||||||
+ if (ret < 0)
|
|
||||||
+ printf ("warning: invalid result from gethostname: %d\n", ret);
|
|
||||||
+ else if (strlen (hostname) == 0)
|
|
||||||
+ puts ("warning: gethostname returned empty string");
|
|
||||||
+ else
|
|
||||||
+ {
|
|
||||||
+ printf ("info: chroot test with IPv6 address in /etc/hosts for: %s\n",
|
|
||||||
+ hostname);
|
|
||||||
+ fp = xfopen (path, "w");
|
|
||||||
+ /* Use an IPv6 address to induce another lookup failure. */
|
|
||||||
+ fprintf (fp, "2001:db8::1 %s\n", hostname);
|
|
||||||
+ xfclose (fp);
|
|
||||||
+ support_isolate_in_subprocess (in_chroot, chroot_dir);
|
|
||||||
+ }
|
|
||||||
+ free (path);
|
|
||||||
+ }
|
|
||||||
+ free (chroot_dir);
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#include <support/test-driver.c>
|
|
@ -1,108 +0,0 @@
|
|||||||
commit 0ef2f4400c06927af34c515555f68840a70ba409
|
|
||||||
Author: Wilco Dijkstra <wdijkstr@arm.com>
|
|
||||||
Date: Wed Sep 19 16:50:18 2018 +0100
|
|
||||||
|
|
||||||
Fix strstr bug with huge needles (bug 23637)
|
|
||||||
|
|
||||||
The generic strstr in GLIBC 2.28 fails to match huge needles. The optimized
|
|
||||||
AVAILABLE macro reads ahead a large fixed amount to reduce the overhead of
|
|
||||||
repeatedly checking for the end of the string. However if the needle length
|
|
||||||
is larger than this, two_way_long_needle may confuse this as meaning the end
|
|
||||||
of the string and return NULL. This is fixed by adding the needle length to
|
|
||||||
the amount to read ahead.
|
|
||||||
|
|
||||||
[BZ #23637]
|
|
||||||
* string/test-strstr.c (pr23637): New function.
|
|
||||||
(test_main): Add tests with longer needles.
|
|
||||||
* string/strcasestr.c (AVAILABLE): Fix readahead distance.
|
|
||||||
* string/strstr.c (AVAILABLE): Likewise.
|
|
||||||
|
|
||||||
(cherry picked from commit 83a552b0bb9fc2a5e80a0ab3723c0a80ce1db9f2)
|
|
||||||
|
|
||||||
diff --git a/string/strcasestr.c b/string/strcasestr.c
|
|
||||||
index 5909fe3cdba88e47..421764bd1b0ff22e 100644
|
|
||||||
--- a/string/strcasestr.c
|
|
||||||
+++ b/string/strcasestr.c
|
|
||||||
@@ -37,8 +37,9 @@
|
|
||||||
/* Two-Way algorithm. */
|
|
||||||
#define RETURN_TYPE char *
|
|
||||||
#define AVAILABLE(h, h_l, j, n_l) \
|
|
||||||
- (((j) + (n_l) <= (h_l)) || ((h_l) += __strnlen ((void*)((h) + (h_l)), 512), \
|
|
||||||
- (j) + (n_l) <= (h_l)))
|
|
||||||
+ (((j) + (n_l) <= (h_l)) \
|
|
||||||
+ || ((h_l) += __strnlen ((void*)((h) + (h_l)), (n_l) + 512), \
|
|
||||||
+ (j) + (n_l) <= (h_l)))
|
|
||||||
#define CHECK_EOL (1)
|
|
||||||
#define RET0_IF_0(a) if (!a) goto ret0
|
|
||||||
#define CANON_ELEMENT(c) TOLOWER (c)
|
|
||||||
diff --git a/string/strstr.c b/string/strstr.c
|
|
||||||
index 265e9f310ce507ce..79ebcc75329d0b17 100644
|
|
||||||
--- a/string/strstr.c
|
|
||||||
+++ b/string/strstr.c
|
|
||||||
@@ -33,8 +33,9 @@
|
|
||||||
|
|
||||||
#define RETURN_TYPE char *
|
|
||||||
#define AVAILABLE(h, h_l, j, n_l) \
|
|
||||||
- (((j) + (n_l) <= (h_l)) || ((h_l) += __strnlen ((void*)((h) + (h_l)), 512), \
|
|
||||||
- (j) + (n_l) <= (h_l)))
|
|
||||||
+ (((j) + (n_l) <= (h_l)) \
|
|
||||||
+ || ((h_l) += __strnlen ((void*)((h) + (h_l)), (n_l) + 512), \
|
|
||||||
+ (j) + (n_l) <= (h_l)))
|
|
||||||
#define CHECK_EOL (1)
|
|
||||||
#define RET0_IF_0(a) if (!a) goto ret0
|
|
||||||
#define FASTSEARCH(S,C,N) (void*) strchr ((void*)(S), (C))
|
|
||||||
diff --git a/string/test-strstr.c b/string/test-strstr.c
|
|
||||||
index 8d99716ff39cc2c2..5861b01b73e4c315 100644
|
|
||||||
--- a/string/test-strstr.c
|
|
||||||
+++ b/string/test-strstr.c
|
|
||||||
@@ -151,6 +151,32 @@ check2 (void)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+#define N 1024
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+pr23637 (void)
|
|
||||||
+{
|
|
||||||
+ char *h = (char*) buf1;
|
|
||||||
+ char *n = (char*) buf2;
|
|
||||||
+
|
|
||||||
+ for (int i = 0; i < N; i++)
|
|
||||||
+ {
|
|
||||||
+ n[i] = 'x';
|
|
||||||
+ h[i] = ' ';
|
|
||||||
+ h[i + N] = 'x';
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ n[N] = '\0';
|
|
||||||
+ h[N * 2] = '\0';
|
|
||||||
+
|
|
||||||
+ /* Ensure we don't match at the first 'x'. */
|
|
||||||
+ h[0] = 'x';
|
|
||||||
+
|
|
||||||
+ char *exp_result = stupid_strstr (h, n);
|
|
||||||
+ FOR_EACH_IMPL (impl, 0)
|
|
||||||
+ check_result (impl, h, n, exp_result);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static int
|
|
||||||
test_main (void)
|
|
||||||
{
|
|
||||||
@@ -158,6 +184,7 @@ test_main (void)
|
|
||||||
|
|
||||||
check1 ();
|
|
||||||
check2 ();
|
|
||||||
+ pr23637 ();
|
|
||||||
|
|
||||||
printf ("%23s", "");
|
|
||||||
FOR_EACH_IMPL (impl, 0)
|
|
||||||
@@ -202,6 +229,9 @@ test_main (void)
|
|
||||||
do_test (15, 9, hlen, klen, 1);
|
|
||||||
do_test (15, 15, hlen, klen, 0);
|
|
||||||
do_test (15, 15, hlen, klen, 1);
|
|
||||||
+
|
|
||||||
+ do_test (15, 15, hlen + klen * 4, klen * 4, 0);
|
|
||||||
+ do_test (15, 15, hlen + klen * 4, klen * 4, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
do_test (0, 0, page_size - 1, 16, 0);
|
|
@ -1,82 +0,0 @@
|
|||||||
commit 2339d6a55eb7a7e040ae888e906adc49eeb59eab
|
|
||||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
|
||||||
Date: Wed Sep 12 08:40:59 2018 -0700
|
|
||||||
|
|
||||||
i386: Use ENTRY and END in start.S [BZ #23606]
|
|
||||||
|
|
||||||
Wrapping the _start function with ENTRY and END to insert ENDBR32 at
|
|
||||||
function entry when CET is enabled. Since _start now includes CFI,
|
|
||||||
without "cfi_undefined (eip)", unwinder may not terminate at _start
|
|
||||||
and we will get
|
|
||||||
|
|
||||||
Program received signal SIGSEGV, Segmentation fault.
|
|
||||||
0xf7dc661e in ?? () from /lib/libgcc_s.so.1
|
|
||||||
Missing separate debuginfos, use: dnf debuginfo-install libgcc-8.2.1-3.0.fc28.i686
|
|
||||||
(gdb) bt
|
|
||||||
#0 0xf7dc661e in ?? () from /lib/libgcc_s.so.1
|
|
||||||
#1 0xf7dc7c18 in _Unwind_Backtrace () from /lib/libgcc_s.so.1
|
|
||||||
#2 0xf7f0d809 in __GI___backtrace (array=array@entry=0xffffc7d0,
|
|
||||||
size=size@entry=20) at ../sysdeps/i386/backtrace.c:127
|
|
||||||
#3 0x08049254 in compare (p1=p1@entry=0xffffcad0, p2=p2@entry=0xffffcad4)
|
|
||||||
at backtrace-tst.c:12
|
|
||||||
#4 0xf7e2a28c in msort_with_tmp (p=p@entry=0xffffca5c, b=b@entry=0xffffcad0,
|
|
||||||
n=n@entry=2) at msort.c:65
|
|
||||||
#5 0xf7e29f64 in msort_with_tmp (n=2, b=0xffffcad0, p=0xffffca5c)
|
|
||||||
at msort.c:53
|
|
||||||
#6 msort_with_tmp (p=p@entry=0xffffca5c, b=b@entry=0xffffcad0, n=n@entry=5)
|
|
||||||
at msort.c:53
|
|
||||||
#7 0xf7e29f64 in msort_with_tmp (n=5, b=0xffffcad0, p=0xffffca5c)
|
|
||||||
at msort.c:53
|
|
||||||
#8 msort_with_tmp (p=p@entry=0xffffca5c, b=b@entry=0xffffcad0, n=n@entry=10)
|
|
||||||
at msort.c:53
|
|
||||||
#9 0xf7e29f64 in msort_with_tmp (n=10, b=0xffffcad0, p=0xffffca5c)
|
|
||||||
at msort.c:53
|
|
||||||
#10 msort_with_tmp (p=p@entry=0xffffca5c, b=b@entry=0xffffcad0, n=n@entry=20)
|
|
||||||
at msort.c:53
|
|
||||||
#11 0xf7e2a5b6 in msort_with_tmp (n=20, b=0xffffcad0, p=0xffffca5c)
|
|
||||||
at msort.c:297
|
|
||||||
#12 __GI___qsort_r (b=b@entry=0xffffcad0, n=n@entry=20, s=s@entry=4,
|
|
||||||
cmp=cmp@entry=0x8049230 <compare>, arg=arg@entry=0x0) at msort.c:297
|
|
||||||
#13 0xf7e2a84d in __GI_qsort (b=b@entry=0xffffcad0, n=n@entry=20, s=s@entry=4,
|
|
||||||
cmp=cmp@entry=0x8049230 <compare>) at msort.c:308
|
|
||||||
#14 0x080490f6 in main (argc=2, argv=0xffffcbd4) at backtrace-tst.c:39
|
|
||||||
|
|
||||||
FAIL: debug/backtrace-tst
|
|
||||||
|
|
||||||
[BZ #23606]
|
|
||||||
* sysdeps/i386/start.S: Include <sysdep.h>
|
|
||||||
(_start): Use ENTRY/END to insert ENDBR32 at entry when CET is
|
|
||||||
enabled. Add cfi_undefined (eip).
|
|
||||||
|
|
||||||
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
|
|
||||||
|
|
||||||
(cherry picked from commit 5a274db4ea363d6b0b92933f085a92daaf1be2f2)
|
|
||||||
|
|
||||||
diff --git a/sysdeps/i386/start.S b/sysdeps/i386/start.S
|
|
||||||
index 91035fa83fb7ee38..e35e9bd31b2cea30 100644
|
|
||||||
--- a/sysdeps/i386/start.S
|
|
||||||
+++ b/sysdeps/i386/start.S
|
|
||||||
@@ -52,10 +52,11 @@
|
|
||||||
NULL
|
|
||||||
*/
|
|
||||||
|
|
||||||
- .text
|
|
||||||
- .globl _start
|
|
||||||
- .type _start,@function
|
|
||||||
-_start:
|
|
||||||
+#include <sysdep.h>
|
|
||||||
+
|
|
||||||
+ENTRY (_start)
|
|
||||||
+ /* Clearing frame pointer is insufficient, use CFI. */
|
|
||||||
+ cfi_undefined (eip)
|
|
||||||
/* Clear the frame pointer. The ABI suggests this be done, to mark
|
|
||||||
the outermost frame obviously. */
|
|
||||||
xorl %ebp, %ebp
|
|
||||||
@@ -131,6 +132,7 @@ _start:
|
|
||||||
1: movl (%esp), %ebx
|
|
||||||
ret
|
|
||||||
#endif
|
|
||||||
+END (_start)
|
|
||||||
|
|
||||||
/* To fulfill the System V/i386 ABI we need this symbol. Yuck, it's so
|
|
||||||
meaningless since we don't support machines < 80386. */
|
|
@ -1,483 +0,0 @@
|
|||||||
commit e5d262effe3a87164308a3f37e61b32d0348692a
|
|
||||||
Author: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
|
|
||||||
Date: Fri Nov 30 18:05:32 2018 -0200
|
|
||||||
|
|
||||||
Fix _dl_profile_fixup data-dependency issue (Bug 23690)
|
|
||||||
|
|
||||||
There is a data-dependency between the fields of struct l_reloc_result
|
|
||||||
and the field used as the initialization guard. Users of the guard
|
|
||||||
expect writes to the structure to be observable when they also observe
|
|
||||||
the guard initialized. The solution for this problem is to use an acquire
|
|
||||||
and release load and store to ensure previous writes to the structure are
|
|
||||||
observable if the guard is initialized.
|
|
||||||
|
|
||||||
The previous implementation used DL_FIXUP_VALUE_ADDR (l_reloc_result->addr)
|
|
||||||
as the initialization guard, making it impossible for some architectures
|
|
||||||
to load and store it atomically, i.e. hppa and ia64, due to its larger size.
|
|
||||||
|
|
||||||
This commit adds an unsigned int to l_reloc_result to be used as the new
|
|
||||||
initialization guard of the struct, making it possible to load and store
|
|
||||||
it atomically in all architectures. The fix ensures that the values
|
|
||||||
observed in l_reloc_result are consistent and do not lead to crashes.
|
|
||||||
The algorithm is documented in the code in elf/dl-runtime.c
|
|
||||||
(_dl_profile_fixup). Not all data races have been eliminated.
|
|
||||||
|
|
||||||
Tested with build-many-glibcs and on powerpc, powerpc64, and powerpc64le.
|
|
||||||
|
|
||||||
[BZ #23690]
|
|
||||||
* elf/dl-runtime.c (_dl_profile_fixup): Guarantee memory
|
|
||||||
modification order when accessing reloc_result->addr.
|
|
||||||
* include/link.h (reloc_result): Add field init.
|
|
||||||
* nptl/Makefile (tests): Add tst-audit-threads.
|
|
||||||
(modules-names): Add tst-audit-threads-mod1 and
|
|
||||||
tst-audit-threads-mod2.
|
|
||||||
Add rules to build tst-audit-threads.
|
|
||||||
* nptl/tst-audit-threads-mod1.c: New file.
|
|
||||||
* nptl/tst-audit-threads-mod2.c: Likewise.
|
|
||||||
* nptl/tst-audit-threads.c: Likewise.
|
|
||||||
* nptl/tst-audit-threads.h: Likewise.
|
|
||||||
|
|
||||||
Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
|
|
||||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
|
||||||
|
|
||||||
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
|
|
||||||
index 63bbc89776..3d2f4a7a76 100644
|
|
||||||
--- a/elf/dl-runtime.c
|
|
||||||
+++ b/elf/dl-runtime.c
|
|
||||||
@@ -183,10 +183,36 @@ _dl_profile_fixup (
|
|
||||||
/* This is the address in the array where we store the result of previous
|
|
||||||
relocations. */
|
|
||||||
struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index];
|
|
||||||
- DL_FIXUP_VALUE_TYPE *resultp = &reloc_result->addr;
|
|
||||||
|
|
||||||
- DL_FIXUP_VALUE_TYPE value = *resultp;
|
|
||||||
- if (DL_FIXUP_VALUE_CODE_ADDR (value) == 0)
|
|
||||||
+ /* CONCURRENCY NOTES:
|
|
||||||
+
|
|
||||||
+ Multiple threads may be calling the same PLT sequence and with
|
|
||||||
+ LD_AUDIT enabled they will be calling into _dl_profile_fixup to
|
|
||||||
+ update the reloc_result with the result of the lazy resolution.
|
|
||||||
+ The reloc_result guard variable is reloc_init, and we use
|
|
||||||
+ acquire/release loads and store to it to ensure that the results of
|
|
||||||
+ the structure are consistent with the loaded value of the guard.
|
|
||||||
+ This does not fix all of the data races that occur when two or more
|
|
||||||
+ threads read reloc_result->reloc_init with a value of zero and read
|
|
||||||
+ and write to that reloc_result concurrently. The expectation is
|
|
||||||
+ generally that while this is a data race it works because the
|
|
||||||
+ threads write the same values. Until the data races are fixed
|
|
||||||
+ there is a potential for problems to arise from these data races.
|
|
||||||
+ The reloc result updates should happen in parallel but there should
|
|
||||||
+ be an atomic RMW which does the final update to the real result
|
|
||||||
+ entry (see bug 23790).
|
|
||||||
+
|
|
||||||
+ The following code uses reloc_result->init set to 0 to indicate if it is
|
|
||||||
+ the first time this object is being relocated, otherwise 1 which
|
|
||||||
+ indicates the object has already been relocated.
|
|
||||||
+
|
|
||||||
+ Reading/Writing from/to reloc_result->reloc_init must not happen
|
|
||||||
+ before previous writes to reloc_result complete as they could
|
|
||||||
+ end-up with an incomplete struct. */
|
|
||||||
+ DL_FIXUP_VALUE_TYPE value;
|
|
||||||
+ unsigned int init = atomic_load_acquire (&reloc_result->init);
|
|
||||||
+
|
|
||||||
+ if (init == 0)
|
|
||||||
{
|
|
||||||
/* This is the first time we have to relocate this object. */
|
|
||||||
const ElfW(Sym) *const symtab
|
|
||||||
@@ -346,19 +372,31 @@ _dl_profile_fixup (
|
|
||||||
|
|
||||||
/* Store the result for later runs. */
|
|
||||||
if (__glibc_likely (! GLRO(dl_bind_not)))
|
|
||||||
- *resultp = value;
|
|
||||||
+ {
|
|
||||||
+ reloc_result->addr = value;
|
|
||||||
+ /* Guarantee all previous writes complete before
|
|
||||||
+ init is updated. See CONCURRENCY NOTES earlier */
|
|
||||||
+ atomic_store_release (&reloc_result->init, 1);
|
|
||||||
+ }
|
|
||||||
+ init = 1;
|
|
||||||
}
|
|
||||||
+ else
|
|
||||||
+ value = reloc_result->addr;
|
|
||||||
|
|
||||||
/* By default we do not call the pltexit function. */
|
|
||||||
long int framesize = -1;
|
|
||||||
|
|
||||||
+
|
|
||||||
#ifdef SHARED
|
|
||||||
/* Auditing checkpoint: report the PLT entering and allow the
|
|
||||||
auditors to change the value. */
|
|
||||||
- if (DL_FIXUP_VALUE_CODE_ADDR (value) != 0 && GLRO(dl_naudit) > 0
|
|
||||||
+ if (GLRO(dl_naudit) > 0
|
|
||||||
/* Don't do anything if no auditor wants to intercept this call. */
|
|
||||||
&& (reloc_result->enterexit & LA_SYMB_NOPLTENTER) == 0)
|
|
||||||
{
|
|
||||||
+ /* Sanity check: DL_FIXUP_VALUE_CODE_ADDR (value) should have been
|
|
||||||
+ initialized earlier in this function or in another thread. */
|
|
||||||
+ assert (DL_FIXUP_VALUE_CODE_ADDR (value) != 0);
|
|
||||||
ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
|
|
||||||
l_info[DT_SYMTAB])
|
|
||||||
+ reloc_result->boundndx);
|
|
||||||
diff --git a/include/link.h b/include/link.h
|
|
||||||
index 5924594548..83b1c34b7b 100644
|
|
||||||
--- a/include/link.h
|
|
||||||
+++ b/include/link.h
|
|
||||||
@@ -216,6 +216,10 @@ struct link_map
|
|
||||||
unsigned int boundndx;
|
|
||||||
uint32_t enterexit;
|
|
||||||
unsigned int flags;
|
|
||||||
+ /* CONCURRENCY NOTE: This is used to guard the concurrent initialization
|
|
||||||
+ of the relocation result across multiple threads. See the more
|
|
||||||
+ detailed notes in elf/dl-runtime.c. */
|
|
||||||
+ unsigned int init;
|
|
||||||
} *l_reloc_result;
|
|
||||||
|
|
||||||
/* Pointer to the version information if available. */
|
|
||||||
diff --git a/nptl/Makefile b/nptl/Makefile
|
|
||||||
index 982e43adfa..98b0aa01c7 100644
|
|
||||||
--- a/nptl/Makefile
|
|
||||||
+++ b/nptl/Makefile
|
|
||||||
@@ -382,7 +382,8 @@ tests += tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx5 \
|
|
||||||
tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3 tst-cleanupx4 \
|
|
||||||
tst-oncex3 tst-oncex4
|
|
||||||
ifeq ($(build-shared),yes)
|
|
||||||
-tests += tst-atfork2 tst-tls4 tst-_res1 tst-fini1 tst-compat-forwarder
|
|
||||||
+tests += tst-atfork2 tst-tls4 tst-_res1 tst-fini1 tst-compat-forwarder \
|
|
||||||
+ tst-audit-threads
|
|
||||||
tests-internal += tst-tls3 tst-tls3-malloc tst-tls5 tst-stackguard1
|
|
||||||
tests-nolibpthread += tst-fini1
|
|
||||||
ifeq ($(have-z-execstack),yes)
|
|
||||||
@@ -394,7 +395,8 @@ modules-names = tst-atfork2mod tst-tls3mod tst-tls4moda tst-tls4modb \
|
|
||||||
tst-tls5mod tst-tls5moda tst-tls5modb tst-tls5modc \
|
|
||||||
tst-tls5modd tst-tls5mode tst-tls5modf tst-stack4mod \
|
|
||||||
tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod \
|
|
||||||
- tst-join7mod tst-compat-forwarder-mod
|
|
||||||
+ tst-join7mod tst-compat-forwarder-mod tst-audit-threads-mod1 \
|
|
||||||
+ tst-audit-threads-mod2
|
|
||||||
extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) \
|
|
||||||
tst-cleanup4aux.o tst-cleanupx4aux.o
|
|
||||||
test-extras += tst-cleanup4aux tst-cleanupx4aux
|
|
||||||
@@ -712,6 +714,14 @@ $(objpfx)tst-compat-forwarder: $(objpfx)tst-compat-forwarder-mod.so
|
|
||||||
|
|
||||||
tst-mutex10-ENV = GLIBC_TUNABLES=glibc.elision.enable=1
|
|
||||||
|
|
||||||
+# Protect against a build using -Wl,-z,now.
|
|
||||||
+LDFLAGS-tst-audit-threads-mod1.so = -Wl,-z,lazy
|
|
||||||
+LDFLAGS-tst-audit-threads-mod2.so = -Wl,-z,lazy
|
|
||||||
+LDFLAGS-tst-audit-threads = -Wl,-z,lazy
|
|
||||||
+$(objpfx)tst-audit-threads: $(objpfx)tst-audit-threads-mod2.so
|
|
||||||
+$(objpfx)tst-audit-threads.out: $(objpfx)tst-audit-threads-mod1.so
|
|
||||||
+tst-audit-threads-ENV = LD_AUDIT=$(objpfx)tst-audit-threads-mod1.so
|
|
||||||
+
|
|
||||||
# The tests here better do not run in parallel
|
|
||||||
ifneq ($(filter %tests,$(MAKECMDGOALS)),)
|
|
||||||
.NOTPARALLEL:
|
|
||||||
diff --git a/nptl/tst-audit-threads-mod1.c b/nptl/tst-audit-threads-mod1.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000..615d5ee512
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/nptl/tst-audit-threads-mod1.c
|
|
||||||
@@ -0,0 +1,74 @@
|
|
||||||
+/* Dummy audit library for test-audit-threads.
|
|
||||||
+
|
|
||||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <http://www.gnu.org/licenses/>. */
|
|
||||||
+
|
|
||||||
+#include <elf.h>
|
|
||||||
+#include <link.h>
|
|
||||||
+#include <stdio.h>
|
|
||||||
+#include <assert.h>
|
|
||||||
+#include <string.h>
|
|
||||||
+
|
|
||||||
+/* We must use a dummy LD_AUDIT module to force the dynamic loader to
|
|
||||||
+ *not* update the real PLT, and instead use a cached value for the
|
|
||||||
+ lazy resolution result. It is the update of that cached value that
|
|
||||||
+ we are testing for correctness by doing this. */
|
|
||||||
+
|
|
||||||
+/* Library to be audited. */
|
|
||||||
+#define LIB "tst-audit-threads-mod2.so"
|
|
||||||
+/* CALLNUM is the number of retNum functions. */
|
|
||||||
+#define CALLNUM 7999
|
|
||||||
+
|
|
||||||
+#define CONCATX(a, b) __CONCAT (a, b)
|
|
||||||
+
|
|
||||||
+static int previous = 0;
|
|
||||||
+
|
|
||||||
+unsigned int
|
|
||||||
+la_version (unsigned int ver)
|
|
||||||
+{
|
|
||||||
+ return 1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+unsigned int
|
|
||||||
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
|
|
||||||
+{
|
|
||||||
+ return LA_FLG_BINDTO | LA_FLG_BINDFROM;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+uintptr_t
|
|
||||||
+CONCATX(la_symbind, __ELF_NATIVE_CLASS) (ElfW(Sym) *sym,
|
|
||||||
+ unsigned int ndx,
|
|
||||||
+ uintptr_t *refcook,
|
|
||||||
+ uintptr_t *defcook,
|
|
||||||
+ unsigned int *flags,
|
|
||||||
+ const char *symname)
|
|
||||||
+{
|
|
||||||
+ const char * retnum = "retNum";
|
|
||||||
+ char * num = strstr (symname, retnum);
|
|
||||||
+ int n;
|
|
||||||
+ /* Validate if the symbols are getting called in the correct order.
|
|
||||||
+ This code is here to verify binutils does not optimize out the PLT
|
|
||||||
+ entries that require the symbol binding. */
|
|
||||||
+ if (num != NULL)
|
|
||||||
+ {
|
|
||||||
+ n = atoi (num);
|
|
||||||
+ assert (n >= previous);
|
|
||||||
+ assert (n <= CALLNUM);
|
|
||||||
+ previous = n;
|
|
||||||
+ }
|
|
||||||
+ return sym->st_value;
|
|
||||||
+}
|
|
||||||
diff --git a/nptl/tst-audit-threads-mod2.c b/nptl/tst-audit-threads-mod2.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000..f9817dd3dc
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/nptl/tst-audit-threads-mod2.c
|
|
||||||
@@ -0,0 +1,22 @@
|
|
||||||
+/* Shared object with a huge number of functions for test-audit-threads.
|
|
||||||
+
|
|
||||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <http://www.gnu.org/licenses/>. */
|
|
||||||
+
|
|
||||||
+/* Define all the retNumN functions in a library. */
|
|
||||||
+#define definenum
|
|
||||||
+#include "tst-audit-threads.h"
|
|
||||||
diff --git a/nptl/tst-audit-threads.c b/nptl/tst-audit-threads.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000..e4bf433bd8
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/nptl/tst-audit-threads.c
|
|
||||||
@@ -0,0 +1,97 @@
|
|
||||||
+/* Test multi-threading using LD_AUDIT.
|
|
||||||
+
|
|
||||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <http://www.gnu.org/licenses/>. */
|
|
||||||
+
|
|
||||||
+/* This test uses a dummy LD_AUDIT library (test-audit-threads-mod1) and a
|
|
||||||
+ library with a huge number of functions in order to validate lazy symbol
|
|
||||||
+ binding with an audit library. We use one thread per CPU to test that
|
|
||||||
+ concurrent lazy resolution does not have any defects which would cause
|
|
||||||
+ the process to fail. We use an LD_AUDIT library to force the testing of
|
|
||||||
+ the relocation resolution caching code in the dynamic loader i.e.
|
|
||||||
+ _dl_runtime_profile and _dl_profile_fixup. */
|
|
||||||
+
|
|
||||||
+#include <support/xthread.h>
|
|
||||||
+#include <strings.h>
|
|
||||||
+#include <stdlib.h>
|
|
||||||
+#include <sys/sysinfo.h>
|
|
||||||
+
|
|
||||||
+static int do_test (void);
|
|
||||||
+
|
|
||||||
+/* This test usually takes less than 3s to run. However, there are cases that
|
|
||||||
+ take up to 30s. */
|
|
||||||
+#define TIMEOUT 60
|
|
||||||
+#define TEST_FUNCTION do_test ()
|
|
||||||
+#include "../test-skeleton.c"
|
|
||||||
+
|
|
||||||
+/* Declare the functions we are going to call. */
|
|
||||||
+#define externnum
|
|
||||||
+#include "tst-audit-threads.h"
|
|
||||||
+#undef externnum
|
|
||||||
+
|
|
||||||
+int num_threads;
|
|
||||||
+pthread_barrier_t barrier;
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+sync_all (int num)
|
|
||||||
+{
|
|
||||||
+ pthread_barrier_wait (&barrier);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+call_all_ret_nums (void)
|
|
||||||
+{
|
|
||||||
+ /* Call each function one at a time from all threads. */
|
|
||||||
+#define callnum
|
|
||||||
+#include "tst-audit-threads.h"
|
|
||||||
+#undef callnum
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void *
|
|
||||||
+thread_main (void *unused)
|
|
||||||
+{
|
|
||||||
+ call_all_ret_nums ();
|
|
||||||
+ return NULL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#define STR2(X) #X
|
|
||||||
+#define STR(X) STR2(X)
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+do_test (void)
|
|
||||||
+{
|
|
||||||
+ int i;
|
|
||||||
+ pthread_t *threads;
|
|
||||||
+
|
|
||||||
+ num_threads = get_nprocs ();
|
|
||||||
+ if (num_threads <= 1)
|
|
||||||
+ num_threads = 2;
|
|
||||||
+
|
|
||||||
+ /* Used to synchronize all the threads after calling each retNumN. */
|
|
||||||
+ xpthread_barrier_init (&barrier, NULL, num_threads);
|
|
||||||
+
|
|
||||||
+ threads = (pthread_t *) xcalloc (num_threads, sizeof(pthread_t));
|
|
||||||
+ for (i = 0; i < num_threads; i++)
|
|
||||||
+ threads[i] = xpthread_create(NULL, thread_main, NULL);
|
|
||||||
+
|
|
||||||
+ for (i = 0; i < num_threads; i++)
|
|
||||||
+ xpthread_join(threads[i]);
|
|
||||||
+
|
|
||||||
+ free (threads);
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
diff --git a/nptl/tst-audit-threads.h b/nptl/tst-audit-threads.h
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000..1c9ecc08df
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/nptl/tst-audit-threads.h
|
|
||||||
@@ -0,0 +1,92 @@
|
|
||||||
+/* Helper header for test-audit-threads.
|
|
||||||
+
|
|
||||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <http://www.gnu.org/licenses/>. */
|
|
||||||
+
|
|
||||||
+/* We use this helper to create a large number of functions, all of
|
|
||||||
+ which will be resolved lazily and thus have their PLT updated.
|
|
||||||
+ This is done to provide enough functions that we can statistically
|
|
||||||
+ observe a thread vs. PLT resolution failure if one exists. */
|
|
||||||
+
|
|
||||||
+#define CONCAT(a, b) a ## b
|
|
||||||
+#define NUM(x, y) CONCAT (x, y)
|
|
||||||
+
|
|
||||||
+#define FUNC10(x) \
|
|
||||||
+ FUNC (NUM (x, 0)); \
|
|
||||||
+ FUNC (NUM (x, 1)); \
|
|
||||||
+ FUNC (NUM (x, 2)); \
|
|
||||||
+ FUNC (NUM (x, 3)); \
|
|
||||||
+ FUNC (NUM (x, 4)); \
|
|
||||||
+ FUNC (NUM (x, 5)); \
|
|
||||||
+ FUNC (NUM (x, 6)); \
|
|
||||||
+ FUNC (NUM (x, 7)); \
|
|
||||||
+ FUNC (NUM (x, 8)); \
|
|
||||||
+ FUNC (NUM (x, 9))
|
|
||||||
+
|
|
||||||
+#define FUNC100(x) \
|
|
||||||
+ FUNC10 (NUM (x, 0)); \
|
|
||||||
+ FUNC10 (NUM (x, 1)); \
|
|
||||||
+ FUNC10 (NUM (x, 2)); \
|
|
||||||
+ FUNC10 (NUM (x, 3)); \
|
|
||||||
+ FUNC10 (NUM (x, 4)); \
|
|
||||||
+ FUNC10 (NUM (x, 5)); \
|
|
||||||
+ FUNC10 (NUM (x, 6)); \
|
|
||||||
+ FUNC10 (NUM (x, 7)); \
|
|
||||||
+ FUNC10 (NUM (x, 8)); \
|
|
||||||
+ FUNC10 (NUM (x, 9))
|
|
||||||
+
|
|
||||||
+#define FUNC1000(x) \
|
|
||||||
+ FUNC100 (NUM (x, 0)); \
|
|
||||||
+ FUNC100 (NUM (x, 1)); \
|
|
||||||
+ FUNC100 (NUM (x, 2)); \
|
|
||||||
+ FUNC100 (NUM (x, 3)); \
|
|
||||||
+ FUNC100 (NUM (x, 4)); \
|
|
||||||
+ FUNC100 (NUM (x, 5)); \
|
|
||||||
+ FUNC100 (NUM (x, 6)); \
|
|
||||||
+ FUNC100 (NUM (x, 7)); \
|
|
||||||
+ FUNC100 (NUM (x, 8)); \
|
|
||||||
+ FUNC100 (NUM (x, 9))
|
|
||||||
+
|
|
||||||
+#define FUNC7000() \
|
|
||||||
+ FUNC1000 (1); \
|
|
||||||
+ FUNC1000 (2); \
|
|
||||||
+ FUNC1000 (3); \
|
|
||||||
+ FUNC1000 (4); \
|
|
||||||
+ FUNC1000 (5); \
|
|
||||||
+ FUNC1000 (6); \
|
|
||||||
+ FUNC1000 (7);
|
|
||||||
+
|
|
||||||
+#ifdef FUNC
|
|
||||||
+# undef FUNC
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+#ifdef externnum
|
|
||||||
+# define FUNC(x) extern int CONCAT (retNum, x) (void)
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+#ifdef definenum
|
|
||||||
+# define FUNC(x) int CONCAT (retNum, x) (void) { return x; }
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+#ifdef callnum
|
|
||||||
+# define FUNC(x) CONCAT (retNum, x) (); sync_all (x)
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+/* A value of 7000 functions is chosen as an arbitrarily large
|
|
||||||
+ number of functions that will allow us enough attempts to
|
|
||||||
+ verify lazy resolution operation. */
|
|
||||||
+FUNC7000 ();
|
|
@ -1,35 +0,0 @@
|
|||||||
commit ed643089cd3251038863d32e67ec47b94cd557f3
|
|
||||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
|
||||||
Date: Tue Oct 9 14:31:28 2018 +0100
|
|
||||||
|
|
||||||
Increase timeout of libio/tst-readline
|
|
||||||
|
|
||||||
Increase timeout from the default 20s to 100s. This test makes close to
|
|
||||||
20 million syscalls with distribution:
|
|
||||||
|
|
||||||
12327675 read
|
|
||||||
4143204 lseek
|
|
||||||
929475 close
|
|
||||||
929471 openat
|
|
||||||
92817 fstat
|
|
||||||
1431 write
|
|
||||||
...
|
|
||||||
|
|
||||||
The default timeout assumes each can finish in 1us on average which
|
|
||||||
is not true on slow machines.
|
|
||||||
|
|
||||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
|
||||||
|
|
||||||
* libio/tst-readline.c (TIMEOUT): Define.
|
|
||||||
|
|
||||||
diff --git a/libio/tst-readline.c b/libio/tst-readline.c
|
|
||||||
index 9322ef68da5e38a9..63f5227760d88c63 100644
|
|
||||||
--- a/libio/tst-readline.c
|
|
||||||
+++ b/libio/tst-readline.c
|
|
||||||
@@ -232,5 +232,6 @@ do_test (void)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+#define TIMEOUT 100
|
|
||||||
#define PREPARE prepare
|
|
||||||
#include <support/test-driver.c>
|
|
File diff suppressed because it is too large
Load Diff
@ -1,80 +0,0 @@
|
|||||||
commit 6c3a8a9d868a8deddf0d6dcc785b6d120de90523
|
|
||||||
Author: Paul Pluzhnikov <ppluzhnikov@kazbek.mtv.corp.google.com>
|
|
||||||
Date: Fri Aug 24 18:08:51 2018 -0700
|
|
||||||
|
|
||||||
Fix BZ#23400 (creating temporary files in source tree), and undefined behavior in test.
|
|
||||||
|
|
||||||
diff --git a/stdlib/test-bz22786.c b/stdlib/test-bz22786.c
|
|
||||||
index e7837f98c19fc4bf..d1aa69106ccf6ac5 100644
|
|
||||||
--- a/stdlib/test-bz22786.c
|
|
||||||
+++ b/stdlib/test-bz22786.c
|
|
||||||
@@ -26,28 +26,20 @@
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
+#include <support/check.h>
|
|
||||||
+#include <support/support.h>
|
|
||||||
+#include <support/temp_file.h>
|
|
||||||
#include <support/test-driver.h>
|
|
||||||
#include <libc-diag.h>
|
|
||||||
|
|
||||||
static int
|
|
||||||
do_test (void)
|
|
||||||
{
|
|
||||||
- const char dir[] = "bz22786";
|
|
||||||
- const char lnk[] = "bz22786/symlink";
|
|
||||||
+ const char *dir = support_create_temp_directory ("bz22786.");
|
|
||||||
+ const char *lnk = xasprintf ("%s/symlink", dir);
|
|
||||||
+ const size_t path_len = (size_t) INT_MAX + strlen (lnk) + 1;
|
|
||||||
|
|
||||||
- rmdir (dir);
|
|
||||||
- if (mkdir (dir, 0755) != 0 && errno != EEXIST)
|
|
||||||
- {
|
|
||||||
- printf ("mkdir %s: %m\n", dir);
|
|
||||||
- return EXIT_FAILURE;
|
|
||||||
- }
|
|
||||||
- if (symlink (".", lnk) != 0 && errno != EEXIST)
|
|
||||||
- {
|
|
||||||
- printf ("symlink (%s, %s): %m\n", dir, lnk);
|
|
||||||
- return EXIT_FAILURE;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- const size_t path_len = (size_t) INT_MAX + 1;
|
|
||||||
+ TEST_VERIFY_EXIT (symlink (".", lnk) == 0);
|
|
||||||
|
|
||||||
DIAG_PUSH_NEEDS_COMMENT;
|
|
||||||
#if __GNUC_PREREQ (7, 0)
|
|
||||||
@@ -55,20 +47,14 @@ do_test (void)
|
|
||||||
allocation to succeed for the test to work. */
|
|
||||||
DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
|
|
||||||
#endif
|
|
||||||
- char *path = malloc (path_len);
|
|
||||||
+ char *path = xmalloc (path_len);
|
|
||||||
DIAG_POP_NEEDS_COMMENT;
|
|
||||||
|
|
||||||
- if (path == NULL)
|
|
||||||
- {
|
|
||||||
- printf ("malloc (%zu): %m\n", path_len);
|
|
||||||
- return EXIT_UNSUPPORTED;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- /* Construct very long path = "bz22786/symlink/aaaa....." */
|
|
||||||
- char *p = mempcpy (path, lnk, sizeof (lnk) - 1);
|
|
||||||
+ /* Construct very long path = "/tmp/bz22786.XXXX/symlink/aaaa....." */
|
|
||||||
+ char *p = mempcpy (path, lnk, strlen (lnk));
|
|
||||||
*(p++) = '/';
|
|
||||||
- memset (p, 'a', path_len - (path - p) - 2);
|
|
||||||
- p[path_len - (path - p) - 1] = '\0';
|
|
||||||
+ memset (p, 'a', path_len - (p - path) - 2);
|
|
||||||
+ p[path_len - (p - path) - 1] = '\0';
|
|
||||||
|
|
||||||
/* This call crashes before the fix for bz22786 on 32-bit platforms. */
|
|
||||||
p = realpath (path, NULL);
|
|
||||||
@@ -81,7 +67,6 @@ do_test (void)
|
|
||||||
|
|
||||||
/* Cleanup. */
|
|
||||||
unlink (lnk);
|
|
||||||
- rmdir (dir);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
commit 3bad2358d67d371497079bba4f8eca9c0096f4e2
|
|
||||||
Author: Stefan Liebler <stli@linux.ibm.com>
|
|
||||||
Date: Thu Aug 30 08:44:32 2018 +0200
|
|
||||||
|
|
||||||
Test stdlib/test-bz22786 exits now with unsupported if malloc fails.
|
|
||||||
|
|
||||||
The test tries to allocate more than 2^31 bytes which will always fail on s390
|
|
||||||
as it has maximum 2^31bit of memory.
|
|
||||||
Before commit 6c3a8a9d868a8deddf0d6dcc785b6d120de90523, this test returned
|
|
||||||
unsupported if malloc fails. This patch re enables this behaviour.
|
|
||||||
|
|
||||||
Furthermore support_delete_temp_files() failed to remove the temp directory
|
|
||||||
in this case as it is not empty due to the created symlink.
|
|
||||||
Thus the creation of the symlink is moved behind malloc.
|
|
||||||
|
|
||||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
|
||||||
|
|
||||||
ChangeLog:
|
|
||||||
|
|
||||||
* stdlib/test-bz22786.c (do_test): Return EXIT_UNSUPPORTED
|
|
||||||
if malloc fails.
|
|
||||||
|
|
||||||
diff --git a/stdlib/test-bz22786.c b/stdlib/test-bz22786.c
|
|
||||||
index d1aa69106ccf6ac5..777bf9180f4b5022 100644
|
|
||||||
--- a/stdlib/test-bz22786.c
|
|
||||||
+++ b/stdlib/test-bz22786.c
|
|
||||||
@@ -39,16 +39,25 @@ do_test (void)
|
|
||||||
const char *lnk = xasprintf ("%s/symlink", dir);
|
|
||||||
const size_t path_len = (size_t) INT_MAX + strlen (lnk) + 1;
|
|
||||||
|
|
||||||
- TEST_VERIFY_EXIT (symlink (".", lnk) == 0);
|
|
||||||
-
|
|
||||||
DIAG_PUSH_NEEDS_COMMENT;
|
|
||||||
#if __GNUC_PREREQ (7, 0)
|
|
||||||
/* GCC 7 warns about too-large allocations; here we need such
|
|
||||||
allocation to succeed for the test to work. */
|
|
||||||
DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
|
|
||||||
#endif
|
|
||||||
- char *path = xmalloc (path_len);
|
|
||||||
+ char *path = malloc (path_len);
|
|
||||||
DIAG_POP_NEEDS_COMMENT;
|
|
||||||
+ if (path == NULL)
|
|
||||||
+ {
|
|
||||||
+ printf ("malloc (%zu): %m\n", path_len);
|
|
||||||
+ /* On 31-bit s390 the malloc will always fail as we do not have
|
|
||||||
+ so much memory, and we want to mark the test unsupported.
|
|
||||||
+ Likewise on systems with little physical memory the test will
|
|
||||||
+ fail and should be unsupported. */
|
|
||||||
+ return EXIT_UNSUPPORTED;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ TEST_VERIFY_EXIT (symlink (".", lnk) == 0);
|
|
||||||
|
|
||||||
/* Construct very long path = "/tmp/bz22786.XXXX/symlink/aaaa....." */
|
|
||||||
char *p = mempcpy (path, lnk, strlen (lnk));
|
|
@ -1,65 +0,0 @@
|
|||||||
commit f5e7e95921847bd83186bfe621fc2b48c4de5477
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Tue Oct 30 13:11:47 2018 +0100
|
|
||||||
|
|
||||||
stdlib/test-bz22786: Avoid spurious test failures using alias mappings
|
|
||||||
|
|
||||||
On systems without enough random-access memory, stdlib/test-bz22786
|
|
||||||
will go deeply into swap and time out, even with a substantial
|
|
||||||
TIMEOUTFACTOR. This commit adds a facility to construct repeating
|
|
||||||
strings with alias mappings, so that the requirement for physical
|
|
||||||
memory, and uses it in stdlib/test-bz22786.
|
|
||||||
|
|
||||||
Adjusted here for conflicts due to the previous support/ backport in
|
|
||||||
glibc-rh1638523-1.patch.
|
|
||||||
|
|
||||||
diff --git a/stdlib/test-bz22786.c b/stdlib/test-bz22786.c
|
|
||||||
index 777bf9180f4b5022..bb1e04f2debe9042 100644
|
|
||||||
--- a/stdlib/test-bz22786.c
|
|
||||||
+++ b/stdlib/test-bz22786.c
|
|
||||||
@@ -26,6 +26,7 @@
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
+#include <support/blob_repeat.h>
|
|
||||||
#include <support/check.h>
|
|
||||||
#include <support/support.h>
|
|
||||||
#include <support/temp_file.h>
|
|
||||||
@@ -39,17 +40,12 @@ do_test (void)
|
|
||||||
const char *lnk = xasprintf ("%s/symlink", dir);
|
|
||||||
const size_t path_len = (size_t) INT_MAX + strlen (lnk) + 1;
|
|
||||||
|
|
||||||
- DIAG_PUSH_NEEDS_COMMENT;
|
|
||||||
-#if __GNUC_PREREQ (7, 0)
|
|
||||||
- /* GCC 7 warns about too-large allocations; here we need such
|
|
||||||
- allocation to succeed for the test to work. */
|
|
||||||
- DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
|
|
||||||
-#endif
|
|
||||||
- char *path = malloc (path_len);
|
|
||||||
- DIAG_POP_NEEDS_COMMENT;
|
|
||||||
+ struct support_blob_repeat repeat
|
|
||||||
+ = support_blob_repeat_allocate ("a", 1, path_len);
|
|
||||||
+ char *path = repeat.start;
|
|
||||||
if (path == NULL)
|
|
||||||
{
|
|
||||||
- printf ("malloc (%zu): %m\n", path_len);
|
|
||||||
+ printf ("Repeated allocation (%zu bytes): %m\n", path_len);
|
|
||||||
/* On 31-bit s390 the malloc will always fail as we do not have
|
|
||||||
so much memory, and we want to mark the test unsupported.
|
|
||||||
Likewise on systems with little physical memory the test will
|
|
||||||
@@ -62,7 +58,6 @@ do_test (void)
|
|
||||||
/* Construct very long path = "/tmp/bz22786.XXXX/symlink/aaaa....." */
|
|
||||||
char *p = mempcpy (path, lnk, strlen (lnk));
|
|
||||||
*(p++) = '/';
|
|
||||||
- memset (p, 'a', path_len - (p - path) - 2);
|
|
||||||
p[path_len - (p - path) - 1] = '\0';
|
|
||||||
|
|
||||||
/* This call crashes before the fix for bz22786 on 32-bit platforms. */
|
|
||||||
@@ -76,6 +71,7 @@ do_test (void)
|
|
||||||
|
|
||||||
/* Cleanup. */
|
|
||||||
unlink (lnk);
|
|
||||||
+ support_blob_repeat_free (&repeat);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
commit 07da99aad93c9364acb7efdab47c27ba698f6313
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Tue Oct 30 13:55:01 2018 +0100
|
|
||||||
|
|
||||||
stdlib/tst-strtod-overflow: Switch to support_blob_repeat
|
|
||||||
|
|
||||||
This is another test with an avoidable large memory allocation.
|
|
||||||
|
|
||||||
diff --git a/stdlib/tst-strtod-overflow.c b/stdlib/tst-strtod-overflow.c
|
|
||||||
index d14638d68ef4f471..dc53c1e521443e1d 100644
|
|
||||||
--- a/stdlib/tst-strtod-overflow.c
|
|
||||||
+++ b/stdlib/tst-strtod-overflow.c
|
|
||||||
@@ -19,6 +19,8 @@
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
+#include <support/blob_repeat.h>
|
|
||||||
+#include <support/test-driver.h>
|
|
||||||
|
|
||||||
#define EXPONENT "e-2147483649"
|
|
||||||
#define SIZE 214748364
|
|
||||||
@@ -26,21 +28,23 @@
|
|
||||||
static int
|
|
||||||
do_test (void)
|
|
||||||
{
|
|
||||||
- char *p = malloc (1 + SIZE + sizeof (EXPONENT));
|
|
||||||
- if (p == NULL)
|
|
||||||
+ struct support_blob_repeat repeat = support_blob_repeat_allocate
|
|
||||||
+ ("0", 1, 1 + SIZE + sizeof (EXPONENT));
|
|
||||||
+ if (repeat.size == 0)
|
|
||||||
{
|
|
||||||
- puts ("malloc failed, cannot test for overflow");
|
|
||||||
- return 0;
|
|
||||||
+ puts ("warning: memory allocation failed, cannot test for overflow");
|
|
||||||
+ return EXIT_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
+ char *p = repeat.start;
|
|
||||||
p[0] = '1';
|
|
||||||
- memset (p + 1, '0', SIZE);
|
|
||||||
memcpy (p + 1 + SIZE, EXPONENT, sizeof (EXPONENT));
|
|
||||||
double d = strtod (p, NULL);
|
|
||||||
if (d != 0)
|
|
||||||
{
|
|
||||||
- printf ("strtod returned wrong value: %a\n", d);
|
|
||||||
+ printf ("error: strtod returned wrong value: %a\n", d);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
+ support_blob_repeat_free (&repeat);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
|||||||
commit 60708030536df82616c16aa2f14f533c4362b969
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Tue Oct 30 13:56:40 2018 +0100
|
|
||||||
|
|
||||||
stdlib/test-bz22786: Avoid memory leaks in the test itself
|
|
||||||
|
|
||||||
diff --git a/stdlib/test-bz22786.c b/stdlib/test-bz22786.c
|
|
||||||
index bb1e04f2debe9042..8035e8a394e7d034 100644
|
|
||||||
--- a/stdlib/test-bz22786.c
|
|
||||||
+++ b/stdlib/test-bz22786.c
|
|
||||||
@@ -36,8 +36,8 @@
|
|
||||||
static int
|
|
||||||
do_test (void)
|
|
||||||
{
|
|
||||||
- const char *dir = support_create_temp_directory ("bz22786.");
|
|
||||||
- const char *lnk = xasprintf ("%s/symlink", dir);
|
|
||||||
+ char *dir = support_create_temp_directory ("bz22786.");
|
|
||||||
+ char *lnk = xasprintf ("%s/symlink", dir);
|
|
||||||
const size_t path_len = (size_t) INT_MAX + strlen (lnk) + 1;
|
|
||||||
|
|
||||||
struct support_blob_repeat repeat
|
|
||||||
@@ -72,6 +72,8 @@ do_test (void)
|
|
||||||
/* Cleanup. */
|
|
||||||
unlink (lnk);
|
|
||||||
support_blob_repeat_free (&repeat);
|
|
||||||
+ free (lnk);
|
|
||||||
+ free (dir);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
commit f9b645b4b0a10c43753296ce3fa40053fa44606a
|
|
||||||
Author: Mike Frysinger <vapier@gentoo.org>
|
|
||||||
Date: Wed Apr 24 13:32:22 2019 +0200
|
|
||||||
|
|
||||||
memusagestat: use local glibc when linking [BZ #18465]
|
|
||||||
|
|
||||||
The memusagestat is the only binary that has its own link line which
|
|
||||||
causes it to be linked against the existing installed C library. It
|
|
||||||
has been this way since it was originally committed in 1999, but I
|
|
||||||
don't see any reason as to why. Since we want all the programs we
|
|
||||||
build locally to be against the new copy of glibc, change the build
|
|
||||||
to be like all other programs.
|
|
||||||
|
|
||||||
diff --git a/malloc/Makefile b/malloc/Makefile
|
|
||||||
index 388cf7e9ee3a2569..228a1279a5960d8c 100644
|
|
||||||
--- a/malloc/Makefile
|
|
||||||
+++ b/malloc/Makefile
|
|
||||||
@@ -131,6 +131,7 @@ ifneq ($(cross-compiling),yes)
|
|
||||||
# If the gd library is available we build the `memusagestat' program.
|
|
||||||
ifneq ($(LIBGD),no)
|
|
||||||
others: $(objpfx)memusage
|
|
||||||
+others += memusagestat
|
|
||||||
install-bin = memusagestat
|
|
||||||
install-bin-script += memusage
|
|
||||||
generated += memusagestat memusage
|
|
||||||
@@ -154,8 +155,7 @@ cpp-srcs-left := $(memusagestat-modules)
|
|
||||||
lib := memusagestat
|
|
||||||
include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left))
|
|
||||||
|
|
||||||
-$(objpfx)memusagestat: $(memusagestat-modules:%=$(objpfx)%.o)
|
|
||||||
- $(LINK.o) -o $@ $^ $(libgd-LDFLAGS) -lgd -lpng -lz -lm
|
|
||||||
+LDLIBS-memusagestat = $(libgd-LDFLAGS) -lgd -lpng -lz -lm
|
|
||||||
|
|
||||||
ifeq ($(run-built-tests),yes)
|
|
||||||
ifeq (yes,$(build-shared))
|
|
@ -1,90 +0,0 @@
|
|||||||
commit 94a4e9e4f401ffe829a992820439977ead0a0ce7
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Thu Apr 25 10:41:43 2019 +0200
|
|
||||||
|
|
||||||
Extend BIND_NOW to installed programs with --enable-bind-now
|
|
||||||
|
|
||||||
Commit 2d6ab5df3b675e96ee587ae6a8c2ce004c6b1ba9 ("Document and fix
|
|
||||||
--enable-bind-now [BZ #21015]") extended BIND_NOW to all installed
|
|
||||||
shared objects. This change also covers installed programs.
|
|
||||||
|
|
||||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
|
||||||
|
|
||||||
diff --git a/INSTALL b/INSTALL
|
|
||||||
index d6c8e899fbb47dac..d56e102ec9ed3281 100644
|
|
||||||
--- a/INSTALL
|
|
||||||
+++ b/INSTALL
|
|
||||||
@@ -169,10 +169,10 @@ if 'CFLAGS' is specified it must enable optimization. For example:
|
|
||||||
protection.
|
|
||||||
|
|
||||||
'--enable-bind-now'
|
|
||||||
- Disable lazy binding for installed shared objects. This provides
|
|
||||||
- additional security hardening because it enables full RELRO and a
|
|
||||||
- read-only global offset table (GOT), at the cost of slightly
|
|
||||||
- increased program load times.
|
|
||||||
+ Disable lazy binding for installed shared objects and programs.
|
|
||||||
+ This provides additional security hardening because it enables full
|
|
||||||
+ RELRO and a read-only global offset table (GOT), at the cost of
|
|
||||||
+ slightly increased program load times.
|
|
||||||
|
|
||||||
'--enable-pt_chown'
|
|
||||||
The file 'pt_chown' is a helper binary for 'grantpt' (*note
|
|
||||||
diff --git a/Makeconfig b/Makeconfig
|
|
||||||
index 8dc2fec9dc683416..742c0c0783a14bfa 100644
|
|
||||||
--- a/Makeconfig
|
|
||||||
+++ b/Makeconfig
|
|
||||||
@@ -398,6 +398,8 @@ endif
|
|
||||||
# test modules.
|
|
||||||
ifeq ($(bind-now),yes)
|
|
||||||
LDFLAGS-lib.so += -Wl,-z,now
|
|
||||||
+# Extra flags for dynamically linked non-test main programs.
|
|
||||||
+link-extra-flags += -Wl,-z,now
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Command to run after every final link (executable or shared object).
|
|
||||||
@@ -426,7 +428,7 @@ ifndef +link-pie
|
|
||||||
$(link-extra-libs)
|
|
||||||
+link-pie-after-libc = $(+postctorS) $(+postinit)
|
|
||||||
define +link-pie
|
|
||||||
-$(+link-pie-before-libc) $(rtld-LDFLAGS) $(link-libc) $(+link-pie-after-libc)
|
|
||||||
+$(+link-pie-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) $(link-libc) $(+link-pie-after-libc)
|
|
||||||
$(call after-link,$@)
|
|
||||||
endef
|
|
||||||
define +link-pie-tests
|
|
||||||
@@ -454,7 +456,7 @@ ifndef +link-static
|
|
||||||
$(link-extra-libs-static)
|
|
||||||
+link-static-after-libc = $(+postctorT) $(+postinit)
|
|
||||||
define +link-static
|
|
||||||
-$(+link-static-before-libc) $(link-libc-static) $(+link-static-after-libc)
|
|
||||||
+$(+link-static-before-libc) $(link-extra-flags) $(link-libc-static) $(+link-static-after-libc)
|
|
||||||
$(call after-link,$@)
|
|
||||||
endef
|
|
||||||
define +link-static-tests
|
|
||||||
@@ -485,7 +487,7 @@ else # not build-pie-default
|
|
||||||
$(link-extra-libs)
|
|
||||||
+link-after-libc = $(+postctor) $(+postinit)
|
|
||||||
define +link
|
|
||||||
-$(+link-before-libc) $(rtld-LDFLAGS) $(link-libc) $(+link-after-libc)
|
|
||||||
+$(+link-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) $(link-libc) $(+link-after-libc)
|
|
||||||
$(call after-link,$@)
|
|
||||||
endef
|
|
||||||
define +link-tests
|
|
||||||
diff --git a/manual/install.texi b/manual/install.texi
|
|
||||||
index e757891dc2eebb2e..351d67c68b255f62 100644
|
|
||||||
--- a/manual/install.texi
|
|
||||||
+++ b/manual/install.texi
|
|
||||||
@@ -199,10 +199,10 @@ number of routines called directly from assembler are excluded from this
|
|
||||||
protection.
|
|
||||||
|
|
||||||
@item --enable-bind-now
|
|
||||||
-Disable lazy binding for installed shared objects. This provides
|
|
||||||
-additional security hardening because it enables full RELRO and a
|
|
||||||
-read-only global offset table (GOT), at the cost of slightly increased
|
|
||||||
-program load times.
|
|
||||||
+Disable lazy binding for installed shared objects and programs. This
|
|
||||||
+provides additional security hardening because it enables full RELRO
|
|
||||||
+and a read-only global offset table (GOT), at the cost of slightly
|
|
||||||
+increased program load times.
|
|
||||||
|
|
||||||
@pindex pt_chown
|
|
||||||
@findex grantpt
|
|
@ -1,43 +0,0 @@
|
|||||||
commit b5ffdc48c20ae865b197b67e5a9068a528fbc198
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Thu Apr 25 10:41:52 2019 +0200
|
|
||||||
|
|
||||||
benchtests: Enable BIND_NOW if configured with --enable-bind-now
|
|
||||||
|
|
||||||
Benchmarks should reflect distribution build policies, so it makes
|
|
||||||
sense to honor the BIND_NOW configuration for them.
|
|
||||||
|
|
||||||
This commit keeps using $(+link-tests), so that the benchmarks are
|
|
||||||
linked according to the --enable-hardcoded-path-in-tests configure
|
|
||||||
option.
|
|
||||||
|
|
||||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
|
||||||
|
|
||||||
diff --git a/benchtests/Makefile b/benchtests/Makefile
|
|
||||||
index bcd6a9c26d9a0005..28d6b0c43f5bd390 100644
|
|
||||||
--- a/benchtests/Makefile
|
|
||||||
+++ b/benchtests/Makefile
|
|
||||||
@@ -235,13 +235,21 @@ bench-func: $(binaries-bench)
|
|
||||||
scripts/benchout.schema.json; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
-$(timing-type) $(binaries-bench) $(binaries-benchset) \
|
|
||||||
- $(binaries-bench-malloc): %: %.o $(objpfx)json-lib.o \
|
|
||||||
+ifeq ($(bind-now),yes)
|
|
||||||
+link-bench-bind-now = -Wl,-z,now
|
|
||||||
+endif
|
|
||||||
+
|
|
||||||
+bench-link-targets = $(timing-type) $(binaries-bench) $(binaries-benchset) \
|
|
||||||
+ $(binaries-bench-malloc)
|
|
||||||
+
|
|
||||||
+$(bench-link-targets): %: %.o $(objpfx)json-lib.o \
|
|
||||||
$(link-extra-libs-tests) \
|
|
||||||
$(sort $(filter $(common-objpfx)lib%,$(link-libc))) \
|
|
||||||
$(addprefix $(csu-objpfx),start.o) $(+preinit) $(+postinit)
|
|
||||||
$(+link-tests)
|
|
||||||
|
|
||||||
+$(bench-link-targets): LDFLAGS += $(link-bench-bind-now)
|
|
||||||
+
|
|
||||||
$(objpfx)bench-%.c: %-inputs $(bench-deps)
|
|
||||||
{ if [ -n "$($*-INCLUDE)" ]; then \
|
|
||||||
cat $($*-INCLUDE); \
|
|
@ -1,100 +0,0 @@
|
|||||||
commit e30fb31c0ad8d31babd1d0d0f05e37c6579a870b
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Fri Apr 26 07:16:47 2019 +0200
|
|
||||||
|
|
||||||
Makeconfig: Move $(CC) to +link command variables
|
|
||||||
|
|
||||||
This change is needed to add linker flags which come very early in the
|
|
||||||
command linke (before LDFLAGS) and are not applied to test programs
|
|
||||||
(only to installed programs).
|
|
||||||
|
|
||||||
diff --git a/Makeconfig b/Makeconfig
|
|
||||||
index 742c0c0783a14bfa..1ad25fc5a7251aea 100644
|
|
||||||
--- a/Makeconfig
|
|
||||||
+++ b/Makeconfig
|
|
||||||
@@ -415,7 +415,7 @@ link-extra-libs-tests = $(libsupport)
|
|
||||||
|
|
||||||
# Command for linking PIE programs with the C library.
|
|
||||||
ifndef +link-pie
|
|
||||||
-+link-pie-before-libc = $(CC) $(if $($(@F)-no-pie),$(no-pie-ldflag),-pie) \
|
|
||||||
++link-pie-before-libc = $(if $($(@F)-no-pie),$(no-pie-ldflag),-pie) \
|
|
||||||
-Wl,-O1 -nostdlib -nostartfiles -o $@ \
|
|
||||||
$(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \
|
|
||||||
$(combreloc-LDFLAGS) $(relro-LDFLAGS) $(hashstyle-LDFLAGS) \
|
|
||||||
@@ -428,23 +428,24 @@ ifndef +link-pie
|
|
||||||
$(link-extra-libs)
|
|
||||||
+link-pie-after-libc = $(+postctorS) $(+postinit)
|
|
||||||
define +link-pie
|
|
||||||
-$(+link-pie-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) $(link-libc) $(+link-pie-after-libc)
|
|
||||||
+$(CC) $(+link-pie-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) \
|
|
||||||
+ $(link-libc) $(+link-pie-after-libc)
|
|
||||||
$(call after-link,$@)
|
|
||||||
endef
|
|
||||||
define +link-pie-tests
|
|
||||||
-$(+link-pie-before-libc) $(rtld-tests-LDFLAGS) $(link-libc-tests) \
|
|
||||||
- $(+link-pie-after-libc)
|
|
||||||
+$(CC) $(+link-pie-before-libc) $(rtld-tests-LDFLAGS) $(link-libc-tests) \
|
|
||||||
+ $(+link-pie-after-libc)
|
|
||||||
$(call after-link,$@)
|
|
||||||
endef
|
|
||||||
define +link-pie-printers-tests
|
|
||||||
-$(+link-pie-before-libc) $(built-rtld-LDFLAGS) $(link-libc-printers-tests) \
|
|
||||||
- $(+link-pie-after-libc)
|
|
||||||
+$(CC) $(+link-pie-before-libc) $(built-rtld-LDFLAGS) \
|
|
||||||
+ $(link-libc-printers-tests) $(+link-pie-after-libc)
|
|
||||||
$(call after-link,$@)
|
|
||||||
endef
|
|
||||||
endif
|
|
||||||
# Command for statically linking programs with the C library.
|
|
||||||
ifndef +link-static
|
|
||||||
-+link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \
|
|
||||||
++link-static-before-libc = -nostdlib -nostartfiles -static -o $@ \
|
|
||||||
$(if $($(@F)-no-pie),$(no-pie-ldflag),$(default-pie-ldflag)) \
|
|
||||||
$(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \
|
|
||||||
$(firstword $(CRT-$(@F)) $(csu-objpfx)$(real-static-start-installed-name)) \
|
|
||||||
@@ -456,11 +457,13 @@ ifndef +link-static
|
|
||||||
$(link-extra-libs-static)
|
|
||||||
+link-static-after-libc = $(+postctorT) $(+postinit)
|
|
||||||
define +link-static
|
|
||||||
-$(+link-static-before-libc) $(link-extra-flags) $(link-libc-static) $(+link-static-after-libc)
|
|
||||||
+$(CC) $(+link-static-before-libc) $(link-extra-flags) $(link-libc-static) \
|
|
||||||
+ $(+link-static-after-libc)
|
|
||||||
$(call after-link,$@)
|
|
||||||
endef
|
|
||||||
define +link-static-tests
|
|
||||||
-$(+link-static-before-libc) $(link-libc-static-tests) $(+link-static-after-libc)
|
|
||||||
+$(CC) $(+link-static-before-libc) $(link-libc-static-tests) \
|
|
||||||
+ $(+link-static-after-libc)
|
|
||||||
$(call after-link,$@)
|
|
||||||
endef
|
|
||||||
endif
|
|
||||||
@@ -475,7 +478,7 @@ ifeq (yes,$(build-pie-default))
|
|
||||||
+link-tests = $(+link-pie-tests)
|
|
||||||
+link-printers-tests = $(+link-pie-printers-tests)
|
|
||||||
else # not build-pie-default
|
|
||||||
-+link-before-libc = $(CC) -nostdlib -nostartfiles -o $@ \
|
|
||||||
++link-before-libc = -nostdlib -nostartfiles -o $@ \
|
|
||||||
$(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \
|
|
||||||
$(combreloc-LDFLAGS) $(relro-LDFLAGS) $(hashstyle-LDFLAGS) \
|
|
||||||
$(firstword $(CRT-$(@F)) $(csu-objpfx)$(start-installed-name)) \
|
|
||||||
@@ -487,16 +490,17 @@ else # not build-pie-default
|
|
||||||
$(link-extra-libs)
|
|
||||||
+link-after-libc = $(+postctor) $(+postinit)
|
|
||||||
define +link
|
|
||||||
-$(+link-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) $(link-libc) $(+link-after-libc)
|
|
||||||
+$(CC) $(+link-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) $(link-libc) \
|
|
||||||
+ $(+link-after-libc)
|
|
||||||
$(call after-link,$@)
|
|
||||||
endef
|
|
||||||
define +link-tests
|
|
||||||
-$(+link-before-libc) $(rtld-tests-LDFLAGS) $(link-libc-tests) \
|
|
||||||
+$(CC) $(+link-before-libc) $(rtld-tests-LDFLAGS) $(link-libc-tests) \
|
|
||||||
$(+link-after-libc)
|
|
||||||
$(call after-link,$@)
|
|
||||||
endef
|
|
||||||
define +link-printers-tests
|
|
||||||
-$(+link-before-libc) $(built-rtld-LDFLAGS) $(link-libc-printers-tests) \
|
|
||||||
+$(CC) $(+link-before-libc) $(built-rtld-LDFLAGS) $(link-libc-printers-tests) \
|
|
||||||
$(+link-after-libc)
|
|
||||||
$(call after-link,$@)
|
|
||||||
endef
|
|
@ -1,74 +0,0 @@
|
|||||||
commit a8ff215e56050a907189e713fd449bcafe99ff6b
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Fri Apr 26 07:16:30 2019 +0200
|
|
||||||
|
|
||||||
Makeconfig: Move -Wl,-rpath-link options before library references
|
|
||||||
|
|
||||||
Previously, the -Wl,-rpath-link options came after the libraries
|
|
||||||
injected using LDLIBS-* variables on the link editor command line for
|
|
||||||
main programs. As a result, it could happen that installed libraries
|
|
||||||
that reference glibc libraries used the installed glibc from the system
|
|
||||||
directories, instead of the glibc from the build tree. This can lead to
|
|
||||||
link failures if the wrong version of libpthread.so.0 is used, for
|
|
||||||
instance, due to differences in the internal GLIBC_PRIVATE interfaces,
|
|
||||||
as seen with memusagestat and -lgd after commit
|
|
||||||
f9b645b4b0a10c43753296ce3fa40053fa44606a ("memusagestat: use local glibc
|
|
||||||
when linking [BZ #18465]").
|
|
||||||
|
|
||||||
The isolation is necessarily imperfect because these installed
|
|
||||||
libraries are linked against the installed glibc in the system
|
|
||||||
directories. However, in most cases, the built glibc will be newer
|
|
||||||
than the installed glibc, and this link is permitted because of the
|
|
||||||
ABI backwards compatibility glibc provides.
|
|
||||||
|
|
||||||
diff --git a/Makeconfig b/Makeconfig
|
|
||||||
index 1ad25fc5a7251aea..e315fb8a75ca5063 100644
|
|
||||||
--- a/Makeconfig
|
|
||||||
+++ b/Makeconfig
|
|
||||||
@@ -428,8 +428,8 @@ ifndef +link-pie
|
|
||||||
$(link-extra-libs)
|
|
||||||
+link-pie-after-libc = $(+postctorS) $(+postinit)
|
|
||||||
define +link-pie
|
|
||||||
-$(CC) $(+link-pie-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) \
|
|
||||||
- $(link-libc) $(+link-pie-after-libc)
|
|
||||||
+$(CC) $(link-libc-rpath-link) $(+link-pie-before-libc) $(rtld-LDFLAGS) \
|
|
||||||
+ $(link-extra-flags) $(link-libc) $(+link-pie-after-libc)
|
|
||||||
$(call after-link,$@)
|
|
||||||
endef
|
|
||||||
define +link-pie-tests
|
|
||||||
@@ -490,8 +490,8 @@ else # not build-pie-default
|
|
||||||
$(link-extra-libs)
|
|
||||||
+link-after-libc = $(+postctor) $(+postinit)
|
|
||||||
define +link
|
|
||||||
-$(CC) $(+link-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) $(link-libc) \
|
|
||||||
- $(+link-after-libc)
|
|
||||||
+$(CC) $(link-libc-rpath-link) $(+link-before-libc) $(rtld-LDFLAGS) \
|
|
||||||
+ $(link-extra-flags) $(link-libc) $(+link-after-libc)
|
|
||||||
$(call after-link,$@)
|
|
||||||
endef
|
|
||||||
define +link-tests
|
|
||||||
@@ -552,6 +552,15 @@ ifeq (yes,$(build-shared))
|
|
||||||
link-libc-rpath = -Wl,-rpath=$(rpath-link)
|
|
||||||
link-libc-rpath-link = -Wl,-rpath-link=$(rpath-link)
|
|
||||||
|
|
||||||
+# For programs which are not tests, $(link-libc-rpath-link) is added
|
|
||||||
+# directly in $(+link), $(+link-pie) above, so that -Wl,-rpath-link
|
|
||||||
+# comes before the expansion of LDLIBS-* and affects libraries added
|
|
||||||
+# there. For shared objects, -Wl,-rpath-link is added via
|
|
||||||
+# $(build-shlib-helper) and $(build-module-helper) in Makerules (also
|
|
||||||
+# before the expansion of LDLIBS-* variables).
|
|
||||||
+
|
|
||||||
+# Tests use -Wl,-rpath instead of -Wl,-rpath-link for
|
|
||||||
+# build-hardcoded-path-in-tests.
|
|
||||||
ifeq (yes,$(build-hardcoded-path-in-tests))
|
|
||||||
link-libc-tests-rpath-link = $(link-libc-rpath)
|
|
||||||
else
|
|
||||||
@@ -562,7 +571,7 @@ link-libc-before-gnulib = $(common-objpfx)libc.so$(libc.so-version) \
|
|
||||||
$(common-objpfx)$(patsubst %,$(libtype.oS),c) \
|
|
||||||
$(as-needed) $(elf-objpfx)ld.so \
|
|
||||||
$(no-as-needed)
|
|
||||||
-link-libc = $(link-libc-rpath-link) $(link-libc-before-gnulib) $(gnulib)
|
|
||||||
+link-libc = $(link-libc-before-gnulib) $(gnulib)
|
|
||||||
|
|
||||||
link-libc-tests-after-rpath-link = $(link-libc-before-gnulib) $(gnulib-tests)
|
|
||||||
link-libc-tests = $(link-libc-tests-rpath-link) \
|
|
@ -1,25 +0,0 @@
|
|||||||
commit c57afec0a9b318bb691e0f5fa4e9681cf30df7a4
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Fri Apr 26 07:16:56 2019 +0200
|
|
||||||
|
|
||||||
elf: Link sotruss-lib.so with BIND_NOW for --enable-bind-now
|
|
||||||
|
|
||||||
The audit module itself can be linked with BIND_NOW; it does not
|
|
||||||
affect its functionality.
|
|
||||||
|
|
||||||
This should complete the leftovers from commit
|
|
||||||
2d6ab5df3b675e96ee587ae6a8c2ce004c6b1ba9 ("Document and fix
|
|
||||||
--enable-bind-now [BZ #21015]").
|
|
||||||
|
|
||||||
diff --git a/elf/Makefile b/elf/Makefile
|
|
||||||
index f5285b99e22fe84d..9194339836900b9d 100644
|
|
||||||
--- a/elf/Makefile
|
|
||||||
+++ b/elf/Makefile
|
|
||||||
@@ -133,6 +133,7 @@ install-others += $(inst_auditdir)/sotruss-lib.so
|
|
||||||
install-bin-script += sotruss
|
|
||||||
generated += sotruss
|
|
||||||
libof-sotruss-lib = extramodules
|
|
||||||
+LDFLAGS-sotruss-lib.so += $(z-now-$(bind-now))
|
|
||||||
$(objpfx)sotruss-lib.so: $(objpfx)sotruss-lib.os
|
|
||||||
$(build-module-asneeded)
|
|
||||||
$(objpfx)sotruss-lib.so: $(common-objpfx)libc.so $(objpfx)ld.so \
|
|
@ -1,41 +0,0 @@
|
|||||||
commit c3d8dc45c9df199b8334599a6cbd98c9950dba62
|
|
||||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
|
||||||
Date: Thu Oct 11 15:18:40 2018 -0300
|
|
||||||
|
|
||||||
x86: Fix Haswell strong flags (BZ#23709)
|
|
||||||
|
|
||||||
Th commit 'Disable TSX on some Haswell processors.' (2702856bf4) changed the
|
|
||||||
default flags for Haswell models. Previously, new models were handled by the
|
|
||||||
default switch path, which assumed a Core i3/i5/i7 if AVX is available. After
|
|
||||||
the patch, Haswell models (0x3f, 0x3c, 0x45, 0x46) do not set the flags
|
|
||||||
Fast_Rep_String, Fast_Unaligned_Load, Fast_Unaligned_Copy, and
|
|
||||||
Prefer_PMINUB_for_stringop (only the TSX one).
|
|
||||||
|
|
||||||
This patch fixes it by disentangle the TSX flag handling from the memory
|
|
||||||
optimization ones. The strstr case cited on patch now selects the
|
|
||||||
__strstr_sse2_unaligned as expected for the Haswell cpu.
|
|
||||||
|
|
||||||
Checked on x86_64-linux-gnu.
|
|
||||||
|
|
||||||
[BZ #23709]
|
|
||||||
* sysdeps/x86/cpu-features.c (init_cpu_features): Set TSX bits
|
|
||||||
independently of other flags.
|
|
||||||
|
|
||||||
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
|
|
||||||
index ea0b64fdb962a934..4695ac80d4148327 100644
|
|
||||||
--- a/sysdeps/x86/cpu-features.c
|
|
||||||
+++ b/sysdeps/x86/cpu-features.c
|
|
||||||
@@ -316,7 +316,13 @@ init_cpu_features (struct cpu_features *cpu_features)
|
|
||||||
| bit_arch_Fast_Unaligned_Copy
|
|
||||||
| bit_arch_Prefer_PMINUB_for_stringop);
|
|
||||||
break;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
+ /* Disable TSX on some Haswell processors to avoid TSX on kernels that
|
|
||||||
+ weren't updated with the latest microcode package (which disables
|
|
||||||
+ broken feature by default). */
|
|
||||||
+ switch (model)
|
|
||||||
+ {
|
|
||||||
case 0x3f:
|
|
||||||
/* Xeon E7 v3 with stepping >= 4 has working TSX. */
|
|
||||||
if (stepping >= 4)
|
|
@ -1,230 +0,0 @@
|
|||||||
commit bcdaad21d4635931d1bd3b54a7894276925d081d
|
|
||||||
Author: DJ Delorie <dj@delorie.com>
|
|
||||||
Date: Tue Nov 20 13:24:09 2018 -0500
|
|
||||||
|
|
||||||
malloc: tcache double free check
|
|
||||||
|
|
||||||
* malloc/malloc.c (tcache_entry): Add key field.
|
|
||||||
(tcache_put): Set it.
|
|
||||||
(tcache_get): Likewise.
|
|
||||||
(_int_free): Check for double free in tcache.
|
|
||||||
* malloc/tst-tcfree1.c: New.
|
|
||||||
* malloc/tst-tcfree2.c: New.
|
|
||||||
* malloc/Makefile: Run the new tests.
|
|
||||||
* manual/probes.texi: Document memory_tcache_double_free probe.
|
|
||||||
|
|
||||||
* dlfcn/dlerror.c (check_free): Prevent double frees.
|
|
||||||
|
|
||||||
diff --git a/dlfcn/dlerror.c b/dlfcn/dlerror.c
|
|
||||||
index 33574faab65628ff..96bf92533335036b 100644
|
|
||||||
--- a/dlfcn/dlerror.c
|
|
||||||
+++ b/dlfcn/dlerror.c
|
|
||||||
@@ -198,7 +198,10 @@ check_free (struct dl_action_result *rec)
|
|
||||||
Dl_info info;
|
|
||||||
if (_dl_addr (check_free, &info, &map, NULL) != 0 && map->l_ns == 0)
|
|
||||||
#endif
|
|
||||||
- free ((char *) rec->errstring);
|
|
||||||
+ {
|
|
||||||
+ free ((char *) rec->errstring);
|
|
||||||
+ rec->errstring = NULL;
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/malloc/Makefile b/malloc/Makefile
|
|
||||||
index 7d54bad866f63cb8..e6dfbfc14cb3d140 100644
|
|
||||||
--- a/malloc/Makefile
|
|
||||||
+++ b/malloc/Makefile
|
|
||||||
@@ -38,6 +38,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
|
|
||||||
tst-malloc_info \
|
|
||||||
tst-malloc-too-large \
|
|
||||||
tst-malloc-stats-cancellation \
|
|
||||||
+ tst-tcfree1 tst-tcfree2 \
|
|
||||||
|
|
||||||
tests-static := \
|
|
||||||
tst-interpose-static-nothread \
|
|
||||||
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
|
||||||
index e247c77b7d4de26e..c6b0282e783eaeea 100644
|
|
||||||
--- a/malloc/malloc.c
|
|
||||||
+++ b/malloc/malloc.c
|
|
||||||
@@ -2888,6 +2888,8 @@ mremap_chunk (mchunkptr p, size_t new_size)
|
|
||||||
typedef struct tcache_entry
|
|
||||||
{
|
|
||||||
struct tcache_entry *next;
|
|
||||||
+ /* This field exists to detect double frees. */
|
|
||||||
+ struct tcache_perthread_struct *key;
|
|
||||||
} tcache_entry;
|
|
||||||
|
|
||||||
/* There is one of these for each thread, which contains the
|
|
||||||
@@ -2911,6 +2913,11 @@ tcache_put (mchunkptr chunk, size_t tc_idx)
|
|
||||||
{
|
|
||||||
tcache_entry *e = (tcache_entry *) chunk2mem (chunk);
|
|
||||||
assert (tc_idx < TCACHE_MAX_BINS);
|
|
||||||
+
|
|
||||||
+ /* Mark this chunk as "in the tcache" so the test in _int_free will
|
|
||||||
+ detect a double free. */
|
|
||||||
+ e->key = tcache;
|
|
||||||
+
|
|
||||||
e->next = tcache->entries[tc_idx];
|
|
||||||
tcache->entries[tc_idx] = e;
|
|
||||||
++(tcache->counts[tc_idx]);
|
|
||||||
@@ -2926,6 +2933,7 @@ tcache_get (size_t tc_idx)
|
|
||||||
assert (tcache->entries[tc_idx] > 0);
|
|
||||||
tcache->entries[tc_idx] = e->next;
|
|
||||||
--(tcache->counts[tc_idx]);
|
|
||||||
+ e->key = NULL;
|
|
||||||
return (void *) e;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -4152,6 +4160,26 @@ _int_free (mstate av, mchunkptr p, int have_lock)
|
|
||||||
{
|
|
||||||
size_t tc_idx = csize2tidx (size);
|
|
||||||
|
|
||||||
+ /* Check to see if it's already in the tcache. */
|
|
||||||
+ tcache_entry *e = (tcache_entry *) chunk2mem (p);
|
|
||||||
+
|
|
||||||
+ /* This test succeeds on double free. However, we don't 100%
|
|
||||||
+ trust it (it also matches random payload data at a 1 in
|
|
||||||
+ 2^<size_t> chance), so verify it's not an unlikely coincidence
|
|
||||||
+ before aborting. */
|
|
||||||
+ if (__glibc_unlikely (e->key == tcache && tcache))
|
|
||||||
+ {
|
|
||||||
+ tcache_entry *tmp;
|
|
||||||
+ LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
|
|
||||||
+ for (tmp = tcache->entries[tc_idx];
|
|
||||||
+ tmp;
|
|
||||||
+ tmp = tmp->next)
|
|
||||||
+ if (tmp == e)
|
|
||||||
+ malloc_printerr ("free(): double free detected in tcache 2");
|
|
||||||
+ /* If we get here, it was a coincidence. We've wasted a few
|
|
||||||
+ cycles, but don't abort. */
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (tcache
|
|
||||||
&& tc_idx < mp_.tcache_bins
|
|
||||||
&& tcache->counts[tc_idx] < mp_.tcache_count)
|
|
||||||
diff --git a/malloc/tst-tcfree1.c b/malloc/tst-tcfree1.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000..bc29375ce77304ac
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/malloc/tst-tcfree1.c
|
|
||||||
@@ -0,0 +1,42 @@
|
|
||||||
+/* Test that malloc tcache catches double free.
|
|
||||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <http://www.gnu.org/licenses/>. */
|
|
||||||
+
|
|
||||||
+#include <errno.h>
|
|
||||||
+#include <error.h>
|
|
||||||
+#include <limits.h>
|
|
||||||
+#include <malloc.h>
|
|
||||||
+#include <stdlib.h>
|
|
||||||
+#include <stdio.h>
|
|
||||||
+#include <sys/signal.h>
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+do_test (void)
|
|
||||||
+{
|
|
||||||
+ /* Do one allocation of any size that fits in tcache. */
|
|
||||||
+ char * volatile x = malloc (32);
|
|
||||||
+
|
|
||||||
+ free (x); // puts in tcache
|
|
||||||
+ free (x); // should abort
|
|
||||||
+
|
|
||||||
+ printf("FAIL: tcache double free not detected\n");
|
|
||||||
+ return 1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#define TEST_FUNCTION do_test
|
|
||||||
+#define EXPECTED_SIGNAL SIGABRT
|
|
||||||
+#include <support/test-driver.c>
|
|
||||||
diff --git a/malloc/tst-tcfree2.c b/malloc/tst-tcfree2.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000..17f06bacd411c315
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/malloc/tst-tcfree2.c
|
|
||||||
@@ -0,0 +1,48 @@
|
|
||||||
+/* Test that malloc tcache catches double free.
|
|
||||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <http://www.gnu.org/licenses/>. */
|
|
||||||
+
|
|
||||||
+#include <errno.h>
|
|
||||||
+#include <error.h>
|
|
||||||
+#include <limits.h>
|
|
||||||
+#include <malloc.h>
|
|
||||||
+#include <stdlib.h>
|
|
||||||
+#include <stdio.h>
|
|
||||||
+#include <sys/signal.h>
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+do_test (void)
|
|
||||||
+{
|
|
||||||
+ char * volatile ptrs[20];
|
|
||||||
+ int i;
|
|
||||||
+
|
|
||||||
+ /* Allocate enough small chunks so that when we free them all, the tcache
|
|
||||||
+ is full, and the first one we freed is at the end of its linked list. */
|
|
||||||
+#define COUNT 20
|
|
||||||
+ for (i=0; i<COUNT; i++)
|
|
||||||
+ ptrs[i] = malloc (20);
|
|
||||||
+ for (i=0; i<COUNT; i++)
|
|
||||||
+ free (ptrs[i]);
|
|
||||||
+ free (ptrs[0]);
|
|
||||||
+
|
|
||||||
+ printf("FAIL: tcache double free\n");
|
|
||||||
+ return 1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#define TEST_FUNCTION do_test
|
|
||||||
+#define EXPECTED_SIGNAL SIGABRT
|
|
||||||
+#include <support/test-driver.c>
|
|
||||||
diff --git a/manual/probes.texi b/manual/probes.texi
|
|
||||||
index ab2a3102bb350ef4..0ea560ed78bcfd7e 100644
|
|
||||||
--- a/manual/probes.texi
|
|
||||||
+++ b/manual/probes.texi
|
|
||||||
@@ -243,6 +243,18 @@ This probe is triggered when the
|
|
||||||
value of this tunable.
|
|
||||||
@end deftp
|
|
||||||
|
|
||||||
+@deftp Probe memory_tcache_double_free (void *@var{$arg1}, int @var{$arg2})
|
|
||||||
+This probe is triggered when @code{free} determines that the memory
|
|
||||||
+being freed has probably already been freed, and resides in the
|
|
||||||
+per-thread cache. Note that there is an extremely unlikely chance
|
|
||||||
+that this probe will trigger due to random payload data remaining in
|
|
||||||
+the allocated memory matching the key used to detect double frees.
|
|
||||||
+This probe actually indicates that an expensive linear search of the
|
|
||||||
+tcache, looking for a double free, has happened. Argument @var{$arg1}
|
|
||||||
+is the memory location as passed to @code{free}, Argument @var{$arg2}
|
|
||||||
+is the tcache bin it resides in.
|
|
||||||
+@end deftp
|
|
||||||
+
|
|
||||||
@node Mathematical Function Probes
|
|
||||||
@section Mathematical Function Probes
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
|||||||
commit affec03b713c82c43a5b025dddc21bde3334f41e
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Mon Nov 26 20:06:37 2018 +0100
|
|
||||||
|
|
||||||
malloc: tcache: Validate tc_idx before checking for double-frees [BZ #23907]
|
|
||||||
|
|
||||||
The previous check could read beyond the end of the tcache entry
|
|
||||||
array. If the e->key == tcache cookie check happened to pass, this
|
|
||||||
would result in crashes.
|
|
||||||
|
|
||||||
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
|
||||||
index c6b0282e783eaeea..13c52f376859562d 100644
|
|
||||||
--- a/malloc/malloc.c
|
|
||||||
+++ b/malloc/malloc.c
|
|
||||||
@@ -4159,33 +4159,33 @@ _int_free (mstate av, mchunkptr p, int have_lock)
|
|
||||||
#if USE_TCACHE
|
|
||||||
{
|
|
||||||
size_t tc_idx = csize2tidx (size);
|
|
||||||
-
|
|
||||||
- /* Check to see if it's already in the tcache. */
|
|
||||||
- tcache_entry *e = (tcache_entry *) chunk2mem (p);
|
|
||||||
-
|
|
||||||
- /* This test succeeds on double free. However, we don't 100%
|
|
||||||
- trust it (it also matches random payload data at a 1 in
|
|
||||||
- 2^<size_t> chance), so verify it's not an unlikely coincidence
|
|
||||||
- before aborting. */
|
|
||||||
- if (__glibc_unlikely (e->key == tcache && tcache))
|
|
||||||
+ if (tcache != NULL && tc_idx < mp_.tcache_bins)
|
|
||||||
{
|
|
||||||
- tcache_entry *tmp;
|
|
||||||
- LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
|
|
||||||
- for (tmp = tcache->entries[tc_idx];
|
|
||||||
- tmp;
|
|
||||||
- tmp = tmp->next)
|
|
||||||
- if (tmp == e)
|
|
||||||
- malloc_printerr ("free(): double free detected in tcache 2");
|
|
||||||
- /* If we get here, it was a coincidence. We've wasted a few
|
|
||||||
- cycles, but don't abort. */
|
|
||||||
- }
|
|
||||||
+ /* Check to see if it's already in the tcache. */
|
|
||||||
+ tcache_entry *e = (tcache_entry *) chunk2mem (p);
|
|
||||||
+
|
|
||||||
+ /* This test succeeds on double free. However, we don't 100%
|
|
||||||
+ trust it (it also matches random payload data at a 1 in
|
|
||||||
+ 2^<size_t> chance), so verify it's not an unlikely
|
|
||||||
+ coincidence before aborting. */
|
|
||||||
+ if (__glibc_unlikely (e->key == tcache))
|
|
||||||
+ {
|
|
||||||
+ tcache_entry *tmp;
|
|
||||||
+ LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
|
|
||||||
+ for (tmp = tcache->entries[tc_idx];
|
|
||||||
+ tmp;
|
|
||||||
+ tmp = tmp->next)
|
|
||||||
+ if (tmp == e)
|
|
||||||
+ malloc_printerr ("free(): double free detected in tcache 2");
|
|
||||||
+ /* If we get here, it was a coincidence. We've wasted a
|
|
||||||
+ few cycles, but don't abort. */
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- if (tcache
|
|
||||||
- && tc_idx < mp_.tcache_bins
|
|
||||||
- && tcache->counts[tc_idx] < mp_.tcache_count)
|
|
||||||
- {
|
|
||||||
- tcache_put (p, tc_idx);
|
|
||||||
- return;
|
|
||||||
+ if (tcache->counts[tc_idx] < mp_.tcache_count)
|
|
||||||
+ {
|
|
||||||
+ tcache_put (p, tc_idx);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,89 +0,0 @@
|
|||||||
commit 7c9a7c68363051cfc5fa1ebb96b3b2c1f82dcb76
|
|
||||||
Author: DJ Delorie <dj@redhat.com>
|
|
||||||
Date: Fri Nov 30 22:13:09 2018 -0500
|
|
||||||
|
|
||||||
malloc: Add another test for tcache double free check.
|
|
||||||
|
|
||||||
This one tests for BZ#23907 where the double free
|
|
||||||
test didn't check the tcache bin bounds before dereferencing
|
|
||||||
the bin.
|
|
||||||
|
|
||||||
[BZ #23907]
|
|
||||||
* malloc/tst-tcfree3.c: New.
|
|
||||||
* malloc/Makefile: Add it.
|
|
||||||
|
|
||||||
diff --git a/malloc/Makefile b/malloc/Makefile
|
|
||||||
index e6dfbfc14cb3d140..388cf7e9ee3a2569 100644
|
|
||||||
--- a/malloc/Makefile
|
|
||||||
+++ b/malloc/Makefile
|
|
||||||
@@ -38,7 +38,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
|
|
||||||
tst-malloc_info \
|
|
||||||
tst-malloc-too-large \
|
|
||||||
tst-malloc-stats-cancellation \
|
|
||||||
- tst-tcfree1 tst-tcfree2 \
|
|
||||||
+ tst-tcfree1 tst-tcfree2 tst-tcfree3 \
|
|
||||||
|
|
||||||
tests-static := \
|
|
||||||
tst-interpose-static-nothread \
|
|
||||||
diff --git a/malloc/tst-tcfree3.c b/malloc/tst-tcfree3.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000..016d30ddd8114082
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/malloc/tst-tcfree3.c
|
|
||||||
@@ -0,0 +1,56 @@
|
|
||||||
+/* Test that malloc tcache catches double free.
|
|
||||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <http://www.gnu.org/licenses/>. */
|
|
||||||
+
|
|
||||||
+#include <malloc.h>
|
|
||||||
+#include <string.h>
|
|
||||||
+
|
|
||||||
+/* Prevent GCC from optimizing away any malloc/free pairs. */
|
|
||||||
+#pragma GCC optimize ("O0")
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+do_test (void)
|
|
||||||
+{
|
|
||||||
+ /* Do two allocation of any size that fit in tcache, and one that
|
|
||||||
+ doesn't. */
|
|
||||||
+ int ** volatile a = malloc (32);
|
|
||||||
+ int ** volatile b = malloc (32);
|
|
||||||
+ /* This is just under the mmap threshold. */
|
|
||||||
+ int ** volatile c = malloc (127 * 1024);
|
|
||||||
+
|
|
||||||
+ /* The invalid "tcache bucket" we might dereference will likely end
|
|
||||||
+ up somewhere within this memory block, so make all the accidental
|
|
||||||
+ "next" pointers cause segfaults. BZ #23907. */
|
|
||||||
+ memset (c, 0xff, 127 * 1024);
|
|
||||||
+
|
|
||||||
+ free (a); // puts in tcache
|
|
||||||
+
|
|
||||||
+ /* A is now free and contains the key we use to detect in-tcache.
|
|
||||||
+ Copy the key to the other chunks. */
|
|
||||||
+ memcpy (b, a, 32);
|
|
||||||
+ memcpy (c, a, 32);
|
|
||||||
+
|
|
||||||
+ /* This free tests the "are we in the tcache already" loop with a
|
|
||||||
+ VALID bin but "coincidental" matching key. */
|
|
||||||
+ free (b); // should NOT abort
|
|
||||||
+ /* This free tests the "is it a valid tcache bin" test. */
|
|
||||||
+ free (c); // should NOT abort
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#include <support/test-driver.c>
|
|
@ -1,176 +0,0 @@
|
|||||||
commit a803367bab167f5ec4fde1f0d0ec447707c29520
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Fri Feb 14 20:55:39 2020 +0100
|
|
||||||
|
|
||||||
powerpc64: Add memory protection key support [BZ #23202]
|
|
||||||
|
|
||||||
The 32-bit protection key behavior is somewhat unclear on 32-bit powerpc,
|
|
||||||
so this change is restricted to the 64-bit variants.
|
|
||||||
|
|
||||||
Flag translation is needed because of hardware differences between the
|
|
||||||
POWER implementation (read and write flags) and the Intel implementation
|
|
||||||
(write and read+write flags).
|
|
||||||
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-pkey.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-pkey.h
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000..623b073d5a585d51
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-pkey.h
|
|
||||||
@@ -0,0 +1,55 @@
|
|
||||||
+/* Helper functions for manipulating memory protection keys, for powerpc64.
|
|
||||||
+ Copyright (C) 2017-2020 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <http://www.gnu.org/licenses/>. */
|
|
||||||
+
|
|
||||||
+#ifndef _ARCH_PKEY_H
|
|
||||||
+#define _ARCH_PKEY_H
|
|
||||||
+
|
|
||||||
+/* Read and write access bits in the AMR register. Needs to be
|
|
||||||
+ translated from and to PKEY_DISABLE_* flags. */
|
|
||||||
+#define PKEY_AMR_READ 1UL
|
|
||||||
+#define PKEY_AMR_WRITE 2UL
|
|
||||||
+
|
|
||||||
+/* Return the value of the AMR register. */
|
|
||||||
+static inline unsigned long int
|
|
||||||
+pkey_read (void)
|
|
||||||
+{
|
|
||||||
+ unsigned long int result;
|
|
||||||
+ __asm__ volatile ("mfspr %0, 13" : "=r" (result));
|
|
||||||
+ return result;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* Overwrite the AMR register with VALUE. */
|
|
||||||
+static inline void
|
|
||||||
+pkey_write (unsigned long int value)
|
|
||||||
+{
|
|
||||||
+ __asm__ volatile ("mtspr 13, %0" : : "r" (value));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* Number of the largest supported key. This depends on the width of
|
|
||||||
+ the AMR register. */
|
|
||||||
+#define PKEY_MAX (sizeof (unsigned long int) * 8 / 2 - 1)
|
|
||||||
+_Static_assert (PKEY_MAX == 15 || PKEY_MAX == 31, "PKEY_MAX value");
|
|
||||||
+
|
|
||||||
+/* Translate key number into AMR index position. */
|
|
||||||
+static inline int
|
|
||||||
+pkey_index (int key)
|
|
||||||
+{
|
|
||||||
+ return 2 * (PKEY_MAX - key);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#endif /* _ARCH_PKEY_H */
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/pkey_get.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pkey_get.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000..856ba061b90eabd2
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pkey_get.c
|
|
||||||
@@ -0,0 +1,42 @@
|
|
||||||
+/* Reading the per-thread memory protection key, powerpc64 version.
|
|
||||||
+ Copyright (C) 2017-2020 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <http://www.gnu.org/licenses/>. */
|
|
||||||
+
|
|
||||||
+#include <arch-pkey.h>
|
|
||||||
+#include <errno.h>
|
|
||||||
+#include <sys/mman.h>
|
|
||||||
+
|
|
||||||
+int
|
|
||||||
+pkey_get (int key)
|
|
||||||
+{
|
|
||||||
+ if (key < 0 || key > PKEY_MAX)
|
|
||||||
+ {
|
|
||||||
+ __set_errno (EINVAL);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+ unsigned int index = pkey_index (key);
|
|
||||||
+ unsigned long int amr = pkey_read ();
|
|
||||||
+ unsigned int bits = (amr >> index) & 3;
|
|
||||||
+
|
|
||||||
+ /* Translate from AMR values. PKEY_AMR_READ standing alone is not
|
|
||||||
+ currently representable. */
|
|
||||||
+ if (bits & PKEY_AMR_READ)
|
|
||||||
+ return PKEY_DISABLE_ACCESS;
|
|
||||||
+ else if (bits == PKEY_AMR_WRITE)
|
|
||||||
+ return PKEY_DISABLE_WRITE;
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/pkey_set.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pkey_set.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000..20b372ee2983abd5
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pkey_set.c
|
|
||||||
@@ -0,0 +1,48 @@
|
|
||||||
+/* Changing the per-thread memory protection key, powerpc64 version.
|
|
||||||
+ Copyright (C) 2017-2020 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <http://www.gnu.org/licenses/>. */
|
|
||||||
+
|
|
||||||
+#include <arch-pkey.h>
|
|
||||||
+#include <errno.h>
|
|
||||||
+#include <sys/mman.h>
|
|
||||||
+
|
|
||||||
+int
|
|
||||||
+pkey_set (int key, unsigned int rights)
|
|
||||||
+{
|
|
||||||
+ if (key < 0 || key > PKEY_MAX || rights > 3)
|
|
||||||
+ {
|
|
||||||
+ __set_errno (EINVAL);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Translate to AMR bit values. */
|
|
||||||
+ unsigned long int bits;
|
|
||||||
+ if (rights & PKEY_DISABLE_ACCESS)
|
|
||||||
+ /* The PKEY_DISABLE_WRITE bit does not matter. */
|
|
||||||
+ bits = PKEY_AMR_READ | PKEY_AMR_WRITE;
|
|
||||||
+ else if (rights == PKEY_DISABLE_WRITE)
|
|
||||||
+ bits = PKEY_AMR_WRITE;
|
|
||||||
+ else
|
|
||||||
+ bits = 0;
|
|
||||||
+
|
|
||||||
+ unsigned int index = pkey_index (key);
|
|
||||||
+ unsigned long int mask = 3UL << index;
|
|
||||||
+ unsigned long int amr = pkey_read ();
|
|
||||||
+ amr = (amr & ~mask) | (bits << index);
|
|
||||||
+ pkey_write (amr);
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
@ -1,53 +0,0 @@
|
|||||||
commit 8d42bf859a289944749d9f978c076cd318119867
|
|
||||||
Author: Lucas A. M. Magalhaes <lamm@linux.ibm.com>
|
|
||||||
Date: Mon Feb 17 09:09:52 2020 -0300
|
|
||||||
|
|
||||||
Fix tst-pkey expectations on pkey_get [BZ #23202]
|
|
||||||
|
|
||||||
From the GNU C Library manual, the pkey_set can receive a combination of
|
|
||||||
PKEY_DISABLE_WRITE and PKEY_DISABLE_ACCESS. However PKEY_DISABLE_ACCESS
|
|
||||||
is more restrictive than PKEY_DISABLE_WRITE and includes its behavior.
|
|
||||||
|
|
||||||
The test expects that after setting
|
|
||||||
(PKEY_DISABLE_WRITE|PKEY_DISABLE_ACCESS) pkey_get should return the
|
|
||||||
same. This may not be true as PKEY_DISABLE_ACCESS will succeed in
|
|
||||||
describing the state of the key in this case.
|
|
||||||
|
|
||||||
The pkey behavior during signal handling is different between x86 and
|
|
||||||
POWER. This change make the test compatible with both architectures.
|
|
||||||
|
|
||||||
Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
|
|
||||||
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/tst-pkey.c b/sysdeps/unix/sysv/linux/tst-pkey.c
|
|
||||||
index 5f721d4444490945..600b6f0098def773 100644
|
|
||||||
--- a/sysdeps/unix/sysv/linux/tst-pkey.c
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/tst-pkey.c
|
|
||||||
@@ -37,7 +37,7 @@ static pthread_barrier_t barrier;
|
|
||||||
|
|
||||||
/* The keys used for testing. These have been allocated with access
|
|
||||||
rights set based on their array index. */
|
|
||||||
-enum { key_count = 4 };
|
|
||||||
+enum { key_count = 3 };
|
|
||||||
static int keys[key_count];
|
|
||||||
static volatile int *pages[key_count];
|
|
||||||
|
|
||||||
@@ -111,14 +111,16 @@ check_page_access (int page, bool write)
|
|
||||||
}
|
|
||||||
|
|
||||||
static volatile sig_atomic_t sigusr1_handler_ran;
|
|
||||||
-
|
|
||||||
-/* Used to check that access is revoked in signal handlers. */
|
|
||||||
+/* Used to check the behavior in signal handlers. In x86 all access are
|
|
||||||
+ revoked during signal handling. In PowerPC the key permissions are
|
|
||||||
+ inherited by the interrupted thread. This test accept both approaches. */
|
|
||||||
static void
|
|
||||||
sigusr1_handler (int signum)
|
|
||||||
{
|
|
||||||
TEST_COMPARE (signum, SIGUSR1);
|
|
||||||
for (int i = 0; i < key_count; ++i)
|
|
||||||
- TEST_COMPARE (pkey_get (keys[i]), PKEY_DISABLE_ACCESS);
|
|
||||||
+ TEST_VERIFY (pkey_get (keys[i]) == PKEY_DISABLE_ACCESS
|
|
||||||
+ || pkey_get (keys[i]) == i);
|
|
||||||
sigusr1_handler_ran = 1;
|
|
||||||
}
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
|||||||
commit 70ba28f7ab2923d4e36ffc9d5d2e32357353b25c
|
|
||||||
Author: Lucas A. M. Magalhaes <lamm@linux.ibm.com>
|
|
||||||
Date: Thu Jan 16 10:39:12 2020 -0300
|
|
||||||
|
|
||||||
Fix tst-pkey.c pkey_alloc return checks and manual
|
|
||||||
|
|
||||||
This test was failing in some powerpc systems as it was not checking
|
|
||||||
for ENOSPC return.
|
|
||||||
|
|
||||||
As said on the Linux man-pages and can be observed by the implementation
|
|
||||||
at mm/mprotect.c in the Linux Kernel source. The syscall pkey_alloc can
|
|
||||||
return EINVAL or ENOSPC. ENOSPC will indicate either that all keys are
|
|
||||||
in use or that the kernel does not support pkeys.
|
|
||||||
|
|
||||||
Reviewed-by: Gabriel F. T. Gomes <gabriel@inconstante.net.br>
|
|
||||||
|
|
||||||
diff --git a/manual/memory.texi b/manual/memory.texi
|
|
||||||
index a1435aad1acd3239..4731a38bcc5701e0 100644
|
|
||||||
--- a/manual/memory.texi
|
|
||||||
+++ b/manual/memory.texi
|
|
||||||
@@ -3289,6 +3289,10 @@ in which memory protection keys are disabled.
|
|
||||||
|
|
||||||
@item ENOSPC
|
|
||||||
All available protection keys already have been allocated.
|
|
||||||
+
|
|
||||||
+The system does not implement memory protection keys or runs in a mode
|
|
||||||
+in which memory protection keys are disabled.
|
|
||||||
+
|
|
||||||
@end table
|
|
||||||
@end deftypefun
|
|
||||||
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/tst-pkey.c b/sysdeps/unix/sysv/linux/tst-pkey.c
|
|
||||||
index 600b6f0098def773..40d7e9f24dec3e57 100644
|
|
||||||
--- a/sysdeps/unix/sysv/linux/tst-pkey.c
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/tst-pkey.c
|
|
||||||
@@ -199,6 +199,10 @@ do_test (void)
|
|
||||||
if (errno == EINVAL)
|
|
||||||
FAIL_UNSUPPORTED
|
|
||||||
("CPU does not support memory protection keys: %m");
|
|
||||||
+ if (errno == ENOSPC)
|
|
||||||
+ FAIL_UNSUPPORTED
|
|
||||||
+ ("no keys available or kernel does not support memory"
|
|
||||||
+ " protection keys");
|
|
||||||
FAIL_EXIT1 ("pkey_alloc: %m");
|
|
||||||
}
|
|
||||||
TEST_COMPARE (pkey_get (keys[0]), 0);
|
|
@ -1,36 +0,0 @@
|
|||||||
commit e627106266ad8785457fadbf5bf67ed604d2a353
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Mon May 11 11:20:02 2020 +0200
|
|
||||||
|
|
||||||
POWER: Add context-synchronizing instructions to pkey_write [BZ #25954]
|
|
||||||
|
|
||||||
Sandipan Das reported that,
|
|
||||||
|
|
||||||
"The Power ISA mandates that all writes to the Authority
|
|
||||||
Mask Register (AMR) must always be preceded as well as
|
|
||||||
succeeded by a context-synchronizing instruction. This
|
|
||||||
applies to both the privileged and unprivileged variants
|
|
||||||
of the Move To AMR instruction.
|
|
||||||
|
|
||||||
This [requirement] is from Table 6 of Chapter 11 in page 1134 of Power
|
|
||||||
ISA 3.0B. The document can be found here:
|
|
||||||
<https://ibm.ent.box.com/s/1hzcwkwf8rbju5h9iyf44wm94amnlcrv>
|
|
||||||
"
|
|
||||||
|
|
||||||
See this kernel patch submission:
|
|
||||||
|
|
||||||
<https://lore.kernel.org/linuxppc-dev/5f65cf37be993760de8112a88da194e3ccbb2bf8.1588959697.git.sandipan@linux.ibm.com/>
|
|
||||||
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-pkey.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-pkey.h
|
|
||||||
index 623b073d5a585d51..25d080c9a6f30942 100644
|
|
||||||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-pkey.h
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-pkey.h
|
|
||||||
@@ -37,7 +37,7 @@ pkey_read (void)
|
|
||||||
static inline void
|
|
||||||
pkey_write (unsigned long int value)
|
|
||||||
{
|
|
||||||
- __asm__ volatile ("mtspr 13, %0" : : "r" (value));
|
|
||||||
+ __asm__ volatile ("isync; mtspr 13, %0; isync" : : "r" (value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Number of the largest supported key. This depends on the width of
|
|
@ -1,34 +0,0 @@
|
|||||||
commit 28669f86f6780a18daca264f32d66b1428c9c6f1
|
|
||||||
Author: Stefan Liebler <stli@linux.ibm.com>
|
|
||||||
Date: Thu Sep 6 14:27:03 2018 +0200
|
|
||||||
|
|
||||||
Fix segfault in maybe_script_execute.
|
|
||||||
|
|
||||||
If glibc is built with gcc 8 and -march=z900,
|
|
||||||
the testcase posix/tst-spawn4-compat crashes with a segfault.
|
|
||||||
|
|
||||||
In function maybe_script_execute, the new_argv array is dynamically
|
|
||||||
initialized on stack with (argc + 1) elements.
|
|
||||||
The function wants to add _PATH_BSHELL as the first argument
|
|
||||||
and writes out of bounds of new_argv.
|
|
||||||
There is an off-by-one because maybe_script_execute fails to count
|
|
||||||
the terminating NULL when sizing new_argv.
|
|
||||||
|
|
||||||
ChangeLog:
|
|
||||||
|
|
||||||
* sysdeps/unix/sysv/linux/spawni.c (maybe_script_execute):
|
|
||||||
Increment size of new_argv by one.
|
|
||||||
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c
|
|
||||||
index cf0213ece55c675d..85239cedbf2a5ab5 100644
|
|
||||||
--- a/sysdeps/unix/sysv/linux/spawni.c
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/spawni.c
|
|
||||||
@@ -101,7 +101,7 @@ maybe_script_execute (struct posix_spawn_args *args)
|
|
||||||
ptrdiff_t argc = args->argc;
|
|
||||||
|
|
||||||
/* Construct an argument list for the shell. */
|
|
||||||
- char *new_argv[argc + 1];
|
|
||||||
+ char *new_argv[argc + 2];
|
|
||||||
new_argv[0] = (char *) _PATH_BSHELL;
|
|
||||||
new_argv[1] = (char *) args->file;
|
|
||||||
if (argc > 1)
|
|
@ -1,193 +0,0 @@
|
|||||||
commit 7a16bdbb9ff4122af0a28dc20996c95352011fdd
|
|
||||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
|
||||||
Date: Wed Aug 29 16:36:44 2018 -0300
|
|
||||||
|
|
||||||
Fix misreported errno on preadv2/pwritev2 (BZ#23579)
|
|
||||||
|
|
||||||
The fallback code of Linux wrapper for preadv2/pwritev2 executes
|
|
||||||
regardless of the errno code for preadv2, instead of the case where
|
|
||||||
the syscall is not supported.
|
|
||||||
|
|
||||||
This fixes it by calling the fallback code iff errno is ENOSYS. The
|
|
||||||
patch also adds tests for both invalid file descriptor and invalid
|
|
||||||
iov_len and vector count.
|
|
||||||
|
|
||||||
The only discrepancy between preadv2 and fallback code regarding
|
|
||||||
error reporting is when an invalid flags are used. The fallback code
|
|
||||||
bails out earlier with ENOTSUP instead of EINVAL/EBADF when the syscall
|
|
||||||
is used.
|
|
||||||
|
|
||||||
Checked on x86_64-linux-gnu on a 4.4.0 and 4.15.0 kernel.
|
|
||||||
|
|
||||||
[BZ #23579]
|
|
||||||
* misc/tst-preadvwritev2-common.c (do_test_with_invalid_fd): New
|
|
||||||
test.
|
|
||||||
* misc/tst-preadvwritev2.c, misc/tst-preadvwritev64v2.c (do_test):
|
|
||||||
Call do_test_with_invalid_fd.
|
|
||||||
* sysdeps/unix/sysv/linux/preadv2.c (preadv2): Use fallback code iff
|
|
||||||
errno is ENOSYS.
|
|
||||||
* sysdeps/unix/sysv/linux/preadv64v2.c (preadv64v2): Likewise.
|
|
||||||
* sysdeps/unix/sysv/linux/pwritev2.c (pwritev2): Likewise.
|
|
||||||
* sysdeps/unix/sysv/linux/pwritev64v2.c (pwritev64v2): Likewise.
|
|
||||||
|
|
||||||
diff --git a/misc/tst-preadvwritev2-common.c b/misc/tst-preadvwritev2-common.c
|
|
||||||
index f889a21544947042..50b9da3fea56d288 100644
|
|
||||||
--- a/misc/tst-preadvwritev2-common.c
|
|
||||||
+++ b/misc/tst-preadvwritev2-common.c
|
|
||||||
@@ -19,9 +19,6 @@
|
|
||||||
#include <limits.h>
|
|
||||||
#include <support/check.h>
|
|
||||||
|
|
||||||
-static void
|
|
||||||
-do_test_with_invalid_flags (void)
|
|
||||||
-{
|
|
||||||
#ifndef RWF_HIPRI
|
|
||||||
# define RWF_HIPRI 0
|
|
||||||
#endif
|
|
||||||
@@ -39,6 +36,68 @@ do_test_with_invalid_flags (void)
|
|
||||||
#endif
|
|
||||||
#define RWF_SUPPORTED (RWF_HIPRI | RWF_DSYNC | RWF_SYNC | RWF_NOWAIT \
|
|
||||||
| RWF_APPEND)
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+do_test_with_invalid_fd (void)
|
|
||||||
+{
|
|
||||||
+ char buf[256];
|
|
||||||
+ struct iovec iov = { buf, sizeof buf };
|
|
||||||
+
|
|
||||||
+ /* Check with flag being 0 to use the fallback code which calls pwritev
|
|
||||||
+ or writev. */
|
|
||||||
+ TEST_VERIFY (preadv2 (-1, &iov, 1, -1, 0) == -1);
|
|
||||||
+ TEST_COMPARE (errno, EBADF);
|
|
||||||
+ TEST_VERIFY (pwritev2 (-1, &iov, 1, -1, 0) == -1);
|
|
||||||
+ TEST_COMPARE (errno, EBADF);
|
|
||||||
+
|
|
||||||
+ /* Same tests as before but with flags being different than 0. Since
|
|
||||||
+ there is no emulation for any flag value, fallback code returns
|
|
||||||
+ ENOTSUP. This is different running on a kernel with preadv2/pwritev2
|
|
||||||
+ support, where EBADF is returned). */
|
|
||||||
+ TEST_VERIFY (preadv2 (-1, &iov, 1, 0, RWF_HIPRI) == -1);
|
|
||||||
+ TEST_VERIFY (errno == EBADF || errno == ENOTSUP);
|
|
||||||
+ TEST_VERIFY (pwritev2 (-1, &iov, 1, 0, RWF_HIPRI) == -1);
|
|
||||||
+ TEST_VERIFY (errno == EBADF || errno == ENOTSUP);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+do_test_with_invalid_iov (void)
|
|
||||||
+{
|
|
||||||
+ {
|
|
||||||
+ char buf[256];
|
|
||||||
+ struct iovec iov;
|
|
||||||
+
|
|
||||||
+ iov.iov_base = buf;
|
|
||||||
+ iov.iov_len = (size_t)SSIZE_MAX + 1;
|
|
||||||
+
|
|
||||||
+ TEST_VERIFY (preadv2 (temp_fd, &iov, 1, 0, 0) == -1);
|
|
||||||
+ TEST_COMPARE (errno, EINVAL);
|
|
||||||
+ TEST_VERIFY (pwritev2 (temp_fd, &iov, 1, 0, 0) == -1);
|
|
||||||
+ TEST_COMPARE (errno, EINVAL);
|
|
||||||
+
|
|
||||||
+ /* Same as for invalid file descriptor tests, emulation fallback
|
|
||||||
+ first checks for flag value and return ENOTSUP. */
|
|
||||||
+ TEST_VERIFY (preadv2 (temp_fd, &iov, 1, 0, RWF_HIPRI) == -1);
|
|
||||||
+ TEST_VERIFY (errno == EINVAL || errno == ENOTSUP);
|
|
||||||
+ TEST_VERIFY (pwritev2 (temp_fd, &iov, 1, 0, RWF_HIPRI) == -1);
|
|
||||||
+ TEST_VERIFY (errno == EINVAL || errno == ENOTSUP);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ {
|
|
||||||
+ /* An invalid iovec buffer should trigger an invalid memory access
|
|
||||||
+ or an error (Linux for instance returns EFAULT). */
|
|
||||||
+ struct iovec iov[IOV_MAX+1] = { 0 };
|
|
||||||
+
|
|
||||||
+ TEST_VERIFY (preadv2 (temp_fd, iov, IOV_MAX + 1, 0, RWF_HIPRI) == -1);
|
|
||||||
+ TEST_VERIFY (errno == EINVAL || errno == ENOTSUP);
|
|
||||||
+ TEST_VERIFY (pwritev2 (temp_fd, iov, IOV_MAX + 1, 0, RWF_HIPRI) == -1);
|
|
||||||
+ TEST_VERIFY (errno == EINVAL || errno == ENOTSUP);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+do_test_with_invalid_flags (void)
|
|
||||||
+{
|
|
||||||
/* Set the next bit from the mask of all supported flags. */
|
|
||||||
int invalid_flag = RWF_SUPPORTED != 0 ? __builtin_clz (RWF_SUPPORTED) : 2;
|
|
||||||
invalid_flag = 0x1 << ((sizeof (int) * CHAR_BIT) - invalid_flag);
|
|
||||||
diff --git a/misc/tst-preadvwritev2.c b/misc/tst-preadvwritev2.c
|
|
||||||
index be22802dbe00317f..cb58cbe41ecc639d 100644
|
|
||||||
--- a/misc/tst-preadvwritev2.c
|
|
||||||
+++ b/misc/tst-preadvwritev2.c
|
|
||||||
@@ -30,6 +30,8 @@ do_test (void)
|
|
||||||
{
|
|
||||||
do_test_with_invalid_flags ();
|
|
||||||
do_test_without_offset ();
|
|
||||||
+ do_test_with_invalid_fd ();
|
|
||||||
+ do_test_with_invalid_iov ();
|
|
||||||
|
|
||||||
return do_test_with_offset (0);
|
|
||||||
}
|
|
||||||
diff --git a/misc/tst-preadvwritev64v2.c b/misc/tst-preadvwritev64v2.c
|
|
||||||
index 8d3cc32b284dbf4c..6a9de54c786acc53 100644
|
|
||||||
--- a/misc/tst-preadvwritev64v2.c
|
|
||||||
+++ b/misc/tst-preadvwritev64v2.c
|
|
||||||
@@ -32,6 +32,8 @@ do_test (void)
|
|
||||||
{
|
|
||||||
do_test_with_invalid_flags ();
|
|
||||||
do_test_without_offset ();
|
|
||||||
+ do_test_with_invalid_fd ();
|
|
||||||
+ do_test_with_invalid_iov ();
|
|
||||||
|
|
||||||
return do_test_with_offset (0);
|
|
||||||
}
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/preadv2.c b/sysdeps/unix/sysv/linux/preadv2.c
|
|
||||||
index c8bf0764ef2629fc..bb08cbc5fd96962e 100644
|
|
||||||
--- a/sysdeps/unix/sysv/linux/preadv2.c
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/preadv2.c
|
|
||||||
@@ -32,7 +32,7 @@ preadv2 (int fd, const struct iovec *vector, int count, off_t offset,
|
|
||||||
# ifdef __NR_preadv2
|
|
||||||
ssize_t result = SYSCALL_CANCEL (preadv2, fd, vector, count,
|
|
||||||
LO_HI_LONG (offset), flags);
|
|
||||||
- if (result >= 0)
|
|
||||||
+ if (result >= 0 || errno != ENOSYS)
|
|
||||||
return result;
|
|
||||||
# endif
|
|
||||||
/* Trying to emulate the preadv2 syscall flags is troublesome:
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/preadv64v2.c b/sysdeps/unix/sysv/linux/preadv64v2.c
|
|
||||||
index d7400a0252a8c6a1..b72a047347b1db0e 100644
|
|
||||||
--- a/sysdeps/unix/sysv/linux/preadv64v2.c
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/preadv64v2.c
|
|
||||||
@@ -30,7 +30,7 @@ preadv64v2 (int fd, const struct iovec *vector, int count, off64_t offset,
|
|
||||||
#ifdef __NR_preadv64v2
|
|
||||||
ssize_t result = SYSCALL_CANCEL (preadv64v2, fd, vector, count,
|
|
||||||
LO_HI_LONG (offset), flags);
|
|
||||||
- if (result >= 0)
|
|
||||||
+ if (result >= 0 || errno != ENOSYS)
|
|
||||||
return result;
|
|
||||||
#endif
|
|
||||||
/* Trying to emulate the preadv2 syscall flags is troublesome:
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/pwritev2.c b/sysdeps/unix/sysv/linux/pwritev2.c
|
|
||||||
index 29c2264c8f3d949a..26333ebd43c5f0af 100644
|
|
||||||
--- a/sysdeps/unix/sysv/linux/pwritev2.c
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/pwritev2.c
|
|
||||||
@@ -28,7 +28,7 @@ pwritev2 (int fd, const struct iovec *vector, int count, off_t offset,
|
|
||||||
# ifdef __NR_pwritev2
|
|
||||||
ssize_t result = SYSCALL_CANCEL (pwritev2, fd, vector, count,
|
|
||||||
LO_HI_LONG (offset), flags);
|
|
||||||
- if (result >= 0)
|
|
||||||
+ if (result >= 0 || errno != ENOSYS)
|
|
||||||
return result;
|
|
||||||
# endif
|
|
||||||
/* Trying to emulate the pwritev2 syscall flags is troublesome:
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/pwritev64v2.c b/sysdeps/unix/sysv/linux/pwritev64v2.c
|
|
||||||
index 42da321149bce40d..17ea905aa6a8db94 100644
|
|
||||||
--- a/sysdeps/unix/sysv/linux/pwritev64v2.c
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/pwritev64v2.c
|
|
||||||
@@ -30,7 +30,7 @@ pwritev64v2 (int fd, const struct iovec *vector, int count, off64_t offset,
|
|
||||||
#ifdef __NR_pwritev64v2
|
|
||||||
ssize_t result = SYSCALL_CANCEL (pwritev64v2, fd, vector, count,
|
|
||||||
LO_HI_LONG (offset), flags);
|
|
||||||
- if (result >= 0)
|
|
||||||
+ if (result >= 0 || errno != ENOSYS)
|
|
||||||
return result;
|
|
||||||
#endif
|
|
||||||
/* Trying to emulate the pwritev2 syscall flags is troublesome:
|
|
@ -1,33 +0,0 @@
|
|||||||
commit dae3ed958c3d0090838e49ff4f78c201262b1cf0
|
|
||||||
Author: Rafal Luzynski <digitalfreak@lingonborough.com>
|
|
||||||
Date: Tue Oct 2 23:34:18 2018 +0200
|
|
||||||
|
|
||||||
kl_GL: Fix spelling of Sunday, should be "sapaat" (bug 20209).
|
|
||||||
|
|
||||||
Although CLDR says otherwise, it is confirmed by Oqaasileriffik, the
|
|
||||||
official Greenlandic language regulator, that this change is correct.
|
|
||||||
|
|
||||||
[BZ #20209]
|
|
||||||
* localedata/locales/kl_GL: (abday): Fix spelling of Sun (Sunday),
|
|
||||||
should be "sap" rather than "sab".
|
|
||||||
(day): Fix spelling of Sunday, should be "sapaat" rather than
|
|
||||||
"sabaat".
|
|
||||||
|
|
||||||
diff --git a/localedata/locales/kl_GL b/localedata/locales/kl_GL
|
|
||||||
index 5ab14a31aade8644..5723ce7dcf9c5742 100644
|
|
||||||
--- a/localedata/locales/kl_GL
|
|
||||||
+++ b/localedata/locales/kl_GL
|
|
||||||
@@ -70,11 +70,11 @@ copy "da_DK"
|
|
||||||
END LC_NUMERIC
|
|
||||||
|
|
||||||
LC_TIME
|
|
||||||
-abday "sab";"ata";/
|
|
||||||
+abday "sap";"ata";/
|
|
||||||
"mar";"pin";/
|
|
||||||
"sis";"tal";/
|
|
||||||
"arf"
|
|
||||||
-day "sabaat";/
|
|
||||||
+day "sapaat";/
|
|
||||||
"ataasinngorneq";/
|
|
||||||
"marlunngorneq";/
|
|
||||||
"pingasunngorneq";/
|
|
@ -1,134 +0,0 @@
|
|||||||
commit 7b1f9406761331cf35fe521fbdb592beecf68a2c
|
|
||||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
|
||||||
Date: Fri Sep 28 13:31:19 2018 -0700
|
|
||||||
|
|
||||||
i386: Use _dl_runtime_[resolve|profile]_shstk for SHSTK [BZ #23716]
|
|
||||||
|
|
||||||
When elf_machine_runtime_setup is called to set up resolver, it should
|
|
||||||
use _dl_runtime_resolve_shstk or _dl_runtime_profile_shstk if SHSTK is
|
|
||||||
enabled by kernel.
|
|
||||||
|
|
||||||
Tested on i686 with and without --enable-cet as well as on CET emulator
|
|
||||||
with --enable-cet.
|
|
||||||
|
|
||||||
[BZ #23716]
|
|
||||||
* sysdeps/i386/dl-cet.c: Removed.
|
|
||||||
* sysdeps/i386/dl-machine.h (_dl_runtime_resolve_shstk): New
|
|
||||||
prototype.
|
|
||||||
(_dl_runtime_profile_shstk): Likewise.
|
|
||||||
(elf_machine_runtime_setup): Use _dl_runtime_profile_shstk or
|
|
||||||
_dl_runtime_resolve_shstk if SHSTK is enabled by kernel.
|
|
||||||
|
|
||||||
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
|
|
||||||
|
|
||||||
diff --git a/sysdeps/i386/dl-cet.c b/sysdeps/i386/dl-cet.c
|
|
||||||
deleted file mode 100644
|
|
||||||
index 5d9a4e8d5179b572..0000000000000000
|
|
||||||
--- a/sysdeps/i386/dl-cet.c
|
|
||||||
+++ /dev/null
|
|
||||||
@@ -1,67 +0,0 @@
|
|
||||||
-/* Linux/i386 CET initializers function.
|
|
||||||
- Copyright (C) 2018 Free Software Foundation, Inc.
|
|
||||||
-
|
|
||||||
- The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
- modify it under the terms of the GNU Lesser General Public
|
|
||||||
- License as published by the Free Software Foundation; either
|
|
||||||
- version 2.1 of the License, or (at your option) any later version.
|
|
||||||
-
|
|
||||||
- The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
- Lesser General Public License for more details.
|
|
||||||
-
|
|
||||||
- You should have received a copy of the GNU Lesser General Public
|
|
||||||
- License along with the GNU C Library; if not, see
|
|
||||||
- <http://www.gnu.org/licenses/>. */
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-#define LINKAGE static inline
|
|
||||||
-#define _dl_cet_check cet_check
|
|
||||||
-#include <sysdeps/x86/dl-cet.c>
|
|
||||||
-#undef _dl_cet_check
|
|
||||||
-
|
|
||||||
-#ifdef SHARED
|
|
||||||
-void
|
|
||||||
-_dl_cet_check (struct link_map *main_map, const char *program)
|
|
||||||
-{
|
|
||||||
- cet_check (main_map, program);
|
|
||||||
-
|
|
||||||
- if ((GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_SHSTK))
|
|
||||||
- {
|
|
||||||
- /* Replace _dl_runtime_resolve and _dl_runtime_profile with
|
|
||||||
- _dl_runtime_resolve_shstk and _dl_runtime_profile_shstk,
|
|
||||||
- respectively if SHSTK is enabled. */
|
|
||||||
- extern void _dl_runtime_resolve (Elf32_Word) attribute_hidden;
|
|
||||||
- extern void _dl_runtime_resolve_shstk (Elf32_Word) attribute_hidden;
|
|
||||||
- extern void _dl_runtime_profile (Elf32_Word) attribute_hidden;
|
|
||||||
- extern void _dl_runtime_profile_shstk (Elf32_Word) attribute_hidden;
|
|
||||||
- unsigned int i;
|
|
||||||
- struct link_map *l;
|
|
||||||
- Elf32_Addr *got;
|
|
||||||
-
|
|
||||||
- if (main_map->l_info[DT_JMPREL])
|
|
||||||
- {
|
|
||||||
- got = (Elf32_Addr *) D_PTR (main_map, l_info[DT_PLTGOT]);
|
|
||||||
- if (got[2] == (Elf32_Addr) &_dl_runtime_resolve)
|
|
||||||
- got[2] = (Elf32_Addr) &_dl_runtime_resolve_shstk;
|
|
||||||
- else if (got[2] == (Elf32_Addr) &_dl_runtime_profile)
|
|
||||||
- got[2] = (Elf32_Addr) &_dl_runtime_profile_shstk;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- i = main_map->l_searchlist.r_nlist;
|
|
||||||
- while (i-- > 0)
|
|
||||||
- {
|
|
||||||
- l = main_map->l_initfini[i];
|
|
||||||
- if (l->l_info[DT_JMPREL])
|
|
||||||
- {
|
|
||||||
- got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
|
|
||||||
- if (got[2] == (Elf32_Addr) &_dl_runtime_resolve)
|
|
||||||
- got[2] = (Elf32_Addr) &_dl_runtime_resolve_shstk;
|
|
||||||
- else if (got[2] == (Elf32_Addr) &_dl_runtime_profile)
|
|
||||||
- got[2] = (Elf32_Addr) &_dl_runtime_profile_shstk;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
-}
|
|
||||||
-#endif
|
|
||||||
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
|
|
||||||
index 1afdcbd9ea2626e4..f6cfb90e21015250 100644
|
|
||||||
--- a/sysdeps/i386/dl-machine.h
|
|
||||||
+++ b/sysdeps/i386/dl-machine.h
|
|
||||||
@@ -67,6 +67,11 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
|
||||||
Elf32_Addr *got;
|
|
||||||
extern void _dl_runtime_resolve (Elf32_Word) attribute_hidden;
|
|
||||||
extern void _dl_runtime_profile (Elf32_Word) attribute_hidden;
|
|
||||||
+ extern void _dl_runtime_resolve_shstk (Elf32_Word) attribute_hidden;
|
|
||||||
+ extern void _dl_runtime_profile_shstk (Elf32_Word) attribute_hidden;
|
|
||||||
+ /* Check if SHSTK is enabled by kernel. */
|
|
||||||
+ bool shstk_enabled
|
|
||||||
+ = (GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0;
|
|
||||||
|
|
||||||
if (l->l_info[DT_JMPREL] && lazy)
|
|
||||||
{
|
|
||||||
@@ -93,7 +98,9 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
|
||||||
end in this function. */
|
|
||||||
if (__glibc_unlikely (profile))
|
|
||||||
{
|
|
||||||
- got[2] = (Elf32_Addr) &_dl_runtime_profile;
|
|
||||||
+ got[2] = (shstk_enabled
|
|
||||||
+ ? (Elf32_Addr) &_dl_runtime_profile_shstk
|
|
||||||
+ : (Elf32_Addr) &_dl_runtime_profile);
|
|
||||||
|
|
||||||
if (GLRO(dl_profile) != NULL
|
|
||||||
&& _dl_name_match_p (GLRO(dl_profile), l))
|
|
||||||
@@ -104,7 +111,9 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
|
||||||
else
|
|
||||||
/* This function will get called to fix up the GOT entry indicated by
|
|
||||||
the offset on the stack, and then jump to the resolved address. */
|
|
||||||
- got[2] = (Elf32_Addr) &_dl_runtime_resolve;
|
|
||||||
+ got[2] = (shstk_enabled
|
|
||||||
+ ? (Elf32_Addr) &_dl_runtime_resolve_shstk
|
|
||||||
+ : (Elf32_Addr) &_dl_runtime_resolve);
|
|
||||||
}
|
|
||||||
|
|
||||||
return lazy;
|
|
@ -1,738 +0,0 @@
|
|||||||
commit 403b4feb22dcbc85ace72a361d2a951380372471
|
|
||||||
Author: Stefan Liebler <stli@linux.ibm.com>
|
|
||||||
Date: Wed Oct 17 12:23:04 2018 +0200
|
|
||||||
|
|
||||||
Fix race in pthread_mutex_lock while promoting to PTHREAD_MUTEX_ELISION_NP [BZ #23275]
|
|
||||||
|
|
||||||
The race leads either to pthread_mutex_destroy returning EBUSY
|
|
||||||
or triggering an assertion (See description in bugzilla).
|
|
||||||
|
|
||||||
This patch is fixing the race by ensuring that the elision path is
|
|
||||||
used in all cases if elision is enabled by the GLIBC_TUNABLES framework.
|
|
||||||
|
|
||||||
The __kind variable in struct __pthread_mutex_s is accessed concurrently.
|
|
||||||
Therefore we are now using the atomic macros.
|
|
||||||
|
|
||||||
The new testcase tst-mutex10 is triggering the race on s390x and intel.
|
|
||||||
Presumably also on power, but I don't have access to a power machine
|
|
||||||
with lock-elision. At least the code for power is the same as on the other
|
|
||||||
two architectures.
|
|
||||||
|
|
||||||
ChangeLog:
|
|
||||||
|
|
||||||
[BZ #23275]
|
|
||||||
* nptl/tst-mutex10.c: New File.
|
|
||||||
* nptl/Makefile (tests): Add tst-mutex10.
|
|
||||||
(tst-mutex10-ENV): New variable.
|
|
||||||
* sysdeps/unix/sysv/linux/s390/force-elision.h: (FORCE_ELISION):
|
|
||||||
Ensure that elision path is used if elision is available.
|
|
||||||
* sysdeps/unix/sysv/linux/powerpc/force-elision.h (FORCE_ELISION):
|
|
||||||
Likewise.
|
|
||||||
* sysdeps/unix/sysv/linux/x86/force-elision.h: (FORCE_ELISION):
|
|
||||||
Likewise.
|
|
||||||
* nptl/pthreadP.h (PTHREAD_MUTEX_TYPE, PTHREAD_MUTEX_TYPE_ELISION)
|
|
||||||
(PTHREAD_MUTEX_PSHARED): Use atomic_load_relaxed.
|
|
||||||
* nptl/pthread_mutex_consistent.c (pthread_mutex_consistent): Likewise.
|
|
||||||
* nptl/pthread_mutex_getprioceiling.c (pthread_mutex_getprioceiling):
|
|
||||||
Likewise.
|
|
||||||
* nptl/pthread_mutex_lock.c (__pthread_mutex_lock_full)
|
|
||||||
(__pthread_mutex_cond_lock_adjust): Likewise.
|
|
||||||
* nptl/pthread_mutex_setprioceiling.c (pthread_mutex_setprioceiling):
|
|
||||||
Likewise.
|
|
||||||
* nptl/pthread_mutex_timedlock.c (__pthread_mutex_timedlock): Likewise.
|
|
||||||
* nptl/pthread_mutex_trylock.c (__pthread_mutex_trylock): Likewise.
|
|
||||||
* nptl/pthread_mutex_unlock.c (__pthread_mutex_unlock_full): Likewise.
|
|
||||||
* sysdeps/nptl/bits/thread-shared-types.h (struct __pthread_mutex_s):
|
|
||||||
Add comments.
|
|
||||||
* nptl/pthread_mutex_destroy.c (__pthread_mutex_destroy):
|
|
||||||
Use atomic_load_relaxed and atomic_store_relaxed.
|
|
||||||
* nptl/pthread_mutex_init.c (__pthread_mutex_init):
|
|
||||||
Use atomic_store_relaxed.
|
|
||||||
|
|
||||||
diff --git a/nptl/Makefile b/nptl/Makefile
|
|
||||||
index be8066524cdc57db..49b6faa330c492e0 100644
|
|
||||||
--- a/nptl/Makefile
|
|
||||||
+++ b/nptl/Makefile
|
|
||||||
@@ -241,9 +241,9 @@ LDLIBS-tst-minstack-throw = -lstdc++
|
|
||||||
|
|
||||||
tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
|
|
||||||
tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex5 tst-mutex6 \
|
|
||||||
- tst-mutex7 tst-mutex9 tst-mutex5a tst-mutex7a tst-mutex7robust \
|
|
||||||
- tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 tst-mutexpi5 \
|
|
||||||
- tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a \
|
|
||||||
+ tst-mutex7 tst-mutex9 tst-mutex10 tst-mutex5a tst-mutex7a \
|
|
||||||
+ tst-mutex7robust tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 \
|
|
||||||
+ tst-mutexpi5 tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a \
|
|
||||||
tst-mutexpi9 \
|
|
||||||
tst-spin1 tst-spin2 tst-spin3 tst-spin4 \
|
|
||||||
tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \
|
|
||||||
@@ -709,6 +709,8 @@ endif
|
|
||||||
|
|
||||||
$(objpfx)tst-compat-forwarder: $(objpfx)tst-compat-forwarder-mod.so
|
|
||||||
|
|
||||||
+tst-mutex10-ENV = GLIBC_TUNABLES=glibc.elision.enable=1
|
|
||||||
+
|
|
||||||
# The tests here better do not run in parallel
|
|
||||||
ifneq ($(filter %tests,$(MAKECMDGOALS)),)
|
|
||||||
.NOTPARALLEL:
|
|
||||||
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
|
|
||||||
index 13bdb11133536195..19efe1e35feed5be 100644
|
|
||||||
--- a/nptl/pthreadP.h
|
|
||||||
+++ b/nptl/pthreadP.h
|
|
||||||
@@ -110,19 +110,23 @@ enum
|
|
||||||
};
|
|
||||||
#define PTHREAD_MUTEX_PSHARED_BIT 128
|
|
||||||
|
|
||||||
+/* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
|
||||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
|
||||||
#define PTHREAD_MUTEX_TYPE(m) \
|
|
||||||
- ((m)->__data.__kind & 127)
|
|
||||||
+ (atomic_load_relaxed (&((m)->__data.__kind)) & 127)
|
|
||||||
/* Don't include NO_ELISION, as that type is always the same
|
|
||||||
as the underlying lock type. */
|
|
||||||
#define PTHREAD_MUTEX_TYPE_ELISION(m) \
|
|
||||||
- ((m)->__data.__kind & (127|PTHREAD_MUTEX_ELISION_NP))
|
|
||||||
+ (atomic_load_relaxed (&((m)->__data.__kind)) \
|
|
||||||
+ & (127 | PTHREAD_MUTEX_ELISION_NP))
|
|
||||||
|
|
||||||
#if LLL_PRIVATE == 0 && LLL_SHARED == 128
|
|
||||||
# define PTHREAD_MUTEX_PSHARED(m) \
|
|
||||||
- ((m)->__data.__kind & 128)
|
|
||||||
+ (atomic_load_relaxed (&((m)->__data.__kind)) & 128)
|
|
||||||
#else
|
|
||||||
# define PTHREAD_MUTEX_PSHARED(m) \
|
|
||||||
- (((m)->__data.__kind & 128) ? LLL_SHARED : LLL_PRIVATE)
|
|
||||||
+ ((atomic_load_relaxed (&((m)->__data.__kind)) & 128) \
|
|
||||||
+ ? LLL_SHARED : LLL_PRIVATE)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The kernel when waking robust mutexes on exit never uses
|
|
||||||
diff --git a/nptl/pthread_mutex_consistent.c b/nptl/pthread_mutex_consistent.c
|
|
||||||
index 85b8e1a6cb027e9b..4fbd875430439e4d 100644
|
|
||||||
--- a/nptl/pthread_mutex_consistent.c
|
|
||||||
+++ b/nptl/pthread_mutex_consistent.c
|
|
||||||
@@ -23,8 +23,11 @@
|
|
||||||
int
|
|
||||||
pthread_mutex_consistent (pthread_mutex_t *mutex)
|
|
||||||
{
|
|
||||||
- /* Test whether this is a robust mutex with a dead owner. */
|
|
||||||
- if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0
|
|
||||||
+ /* Test whether this is a robust mutex with a dead owner.
|
|
||||||
+ See concurrency notes regarding __kind in struct __pthread_mutex_s
|
|
||||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
|
||||||
+ if ((atomic_load_relaxed (&(mutex->__data.__kind))
|
|
||||||
+ & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0
|
|
||||||
|| mutex->__data.__owner != PTHREAD_MUTEX_INCONSISTENT)
|
|
||||||
return EINVAL;
|
|
||||||
|
|
||||||
diff --git a/nptl/pthread_mutex_destroy.c b/nptl/pthread_mutex_destroy.c
|
|
||||||
index 5a22611541995778..713ea684962fefc1 100644
|
|
||||||
--- a/nptl/pthread_mutex_destroy.c
|
|
||||||
+++ b/nptl/pthread_mutex_destroy.c
|
|
||||||
@@ -27,12 +27,17 @@ __pthread_mutex_destroy (pthread_mutex_t *mutex)
|
|
||||||
{
|
|
||||||
LIBC_PROBE (mutex_destroy, 1, mutex);
|
|
||||||
|
|
||||||
- if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0
|
|
||||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
|
||||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
|
||||||
+ if ((atomic_load_relaxed (&(mutex->__data.__kind))
|
|
||||||
+ & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0
|
|
||||||
&& mutex->__data.__nusers != 0)
|
|
||||||
return EBUSY;
|
|
||||||
|
|
||||||
- /* Set to an invalid value. */
|
|
||||||
- mutex->__data.__kind = -1;
|
|
||||||
+ /* Set to an invalid value. Relaxed MO is enough as it is undefined behavior
|
|
||||||
+ if the mutex is used after it has been destroyed. But you can reinitialize
|
|
||||||
+ it with pthread_mutex_init. */
|
|
||||||
+ atomic_store_relaxed (&(mutex->__data.__kind), -1);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
diff --git a/nptl/pthread_mutex_getprioceiling.c b/nptl/pthread_mutex_getprioceiling.c
|
|
||||||
index efa37b0d99201f57..ee85949578475f3a 100644
|
|
||||||
--- a/nptl/pthread_mutex_getprioceiling.c
|
|
||||||
+++ b/nptl/pthread_mutex_getprioceiling.c
|
|
||||||
@@ -24,7 +24,9 @@
|
|
||||||
int
|
|
||||||
pthread_mutex_getprioceiling (const pthread_mutex_t *mutex, int *prioceiling)
|
|
||||||
{
|
|
||||||
- if (__builtin_expect ((mutex->__data.__kind
|
|
||||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
|
||||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
|
||||||
+ if (__builtin_expect ((atomic_load_relaxed (&(mutex->__data.__kind))
|
|
||||||
& PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0, 0))
|
|
||||||
return EINVAL;
|
|
||||||
|
|
||||||
diff --git a/nptl/pthread_mutex_init.c b/nptl/pthread_mutex_init.c
|
|
||||||
index d8fe4737289c0bd7..5cf290c272e27915 100644
|
|
||||||
--- a/nptl/pthread_mutex_init.c
|
|
||||||
+++ b/nptl/pthread_mutex_init.c
|
|
||||||
@@ -101,7 +101,7 @@ __pthread_mutex_init (pthread_mutex_t *mutex,
|
|
||||||
memset (mutex, '\0', __SIZEOF_PTHREAD_MUTEX_T);
|
|
||||||
|
|
||||||
/* Copy the values from the attribute. */
|
|
||||||
- mutex->__data.__kind = imutexattr->mutexkind & ~PTHREAD_MUTEXATTR_FLAG_BITS;
|
|
||||||
+ int mutex_kind = imutexattr->mutexkind & ~PTHREAD_MUTEXATTR_FLAG_BITS;
|
|
||||||
|
|
||||||
if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST) != 0)
|
|
||||||
{
|
|
||||||
@@ -111,17 +111,17 @@ __pthread_mutex_init (pthread_mutex_t *mutex,
|
|
||||||
return ENOTSUP;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
- mutex->__data.__kind |= PTHREAD_MUTEX_ROBUST_NORMAL_NP;
|
|
||||||
+ mutex_kind |= PTHREAD_MUTEX_ROBUST_NORMAL_NP;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (imutexattr->mutexkind & PTHREAD_MUTEXATTR_PROTOCOL_MASK)
|
|
||||||
{
|
|
||||||
case PTHREAD_PRIO_INHERIT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
|
|
||||||
- mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_INHERIT_NP;
|
|
||||||
+ mutex_kind |= PTHREAD_MUTEX_PRIO_INHERIT_NP;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PTHREAD_PRIO_PROTECT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
|
|
||||||
- mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_PROTECT_NP;
|
|
||||||
+ mutex_kind |= PTHREAD_MUTEX_PRIO_PROTECT_NP;
|
|
||||||
|
|
||||||
int ceiling = (imutexattr->mutexkind
|
|
||||||
& PTHREAD_MUTEXATTR_PRIO_CEILING_MASK)
|
|
||||||
@@ -145,7 +145,11 @@ __pthread_mutex_init (pthread_mutex_t *mutex,
|
|
||||||
FUTEX_PRIVATE_FLAG FUTEX_WAKE. */
|
|
||||||
if ((imutexattr->mutexkind & (PTHREAD_MUTEXATTR_FLAG_PSHARED
|
|
||||||
| PTHREAD_MUTEXATTR_FLAG_ROBUST)) != 0)
|
|
||||||
- mutex->__data.__kind |= PTHREAD_MUTEX_PSHARED_BIT;
|
|
||||||
+ mutex_kind |= PTHREAD_MUTEX_PSHARED_BIT;
|
|
||||||
+
|
|
||||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
|
||||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
|
||||||
+ atomic_store_relaxed (&(mutex->__data.__kind), mutex_kind);
|
|
||||||
|
|
||||||
/* Default values: mutex not used yet. */
|
|
||||||
// mutex->__count = 0; already done by memset
|
|
||||||
diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c
|
|
||||||
index 1519c142bd6ec5cc..29cc143e6cbf2421 100644
|
|
||||||
--- a/nptl/pthread_mutex_lock.c
|
|
||||||
+++ b/nptl/pthread_mutex_lock.c
|
|
||||||
@@ -62,6 +62,8 @@ static int __pthread_mutex_lock_full (pthread_mutex_t *mutex)
|
|
||||||
int
|
|
||||||
__pthread_mutex_lock (pthread_mutex_t *mutex)
|
|
||||||
{
|
|
||||||
+ /* See concurrency notes regarding mutex type which is loaded from __kind
|
|
||||||
+ in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */
|
|
||||||
unsigned int type = PTHREAD_MUTEX_TYPE_ELISION (mutex);
|
|
||||||
|
|
||||||
LIBC_PROBE (mutex_entry, 1, mutex);
|
|
||||||
@@ -350,8 +352,14 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex)
|
|
||||||
case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
|
|
||||||
case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
|
|
||||||
{
|
|
||||||
- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
|
|
||||||
- int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
|
|
||||||
+ int kind, robust;
|
|
||||||
+ {
|
|
||||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
|
||||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
|
||||||
+ int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind));
|
|
||||||
+ kind = mutex_kind & PTHREAD_MUTEX_KIND_MASK_NP;
|
|
||||||
+ robust = mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
if (robust)
|
|
||||||
{
|
|
||||||
@@ -502,7 +510,10 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex)
|
|
||||||
case PTHREAD_MUTEX_PP_NORMAL_NP:
|
|
||||||
case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
|
|
||||||
{
|
|
||||||
- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
|
|
||||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
|
||||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
|
||||||
+ int kind = atomic_load_relaxed (&(mutex->__data.__kind))
|
|
||||||
+ & PTHREAD_MUTEX_KIND_MASK_NP;
|
|
||||||
|
|
||||||
oldval = mutex->__data.__lock;
|
|
||||||
|
|
||||||
@@ -607,15 +618,18 @@ hidden_def (__pthread_mutex_lock)
|
|
||||||
void
|
|
||||||
__pthread_mutex_cond_lock_adjust (pthread_mutex_t *mutex)
|
|
||||||
{
|
|
||||||
- assert ((mutex->__data.__kind & PTHREAD_MUTEX_PRIO_INHERIT_NP) != 0);
|
|
||||||
- assert ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0);
|
|
||||||
- assert ((mutex->__data.__kind & PTHREAD_MUTEX_PSHARED_BIT) == 0);
|
|
||||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
|
||||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
|
||||||
+ int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind));
|
|
||||||
+ assert ((mutex_kind & PTHREAD_MUTEX_PRIO_INHERIT_NP) != 0);
|
|
||||||
+ assert ((mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0);
|
|
||||||
+ assert ((mutex_kind & PTHREAD_MUTEX_PSHARED_BIT) == 0);
|
|
||||||
|
|
||||||
/* Record the ownership. */
|
|
||||||
pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
|
|
||||||
mutex->__data.__owner = id;
|
|
||||||
|
|
||||||
- if (mutex->__data.__kind == PTHREAD_MUTEX_PI_RECURSIVE_NP)
|
|
||||||
+ if (mutex_kind == PTHREAD_MUTEX_PI_RECURSIVE_NP)
|
|
||||||
++mutex->__data.__count;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
diff --git a/nptl/pthread_mutex_setprioceiling.c b/nptl/pthread_mutex_setprioceiling.c
|
|
||||||
index 8594874f8588b7a8..8306cabcf4e56174 100644
|
|
||||||
--- a/nptl/pthread_mutex_setprioceiling.c
|
|
||||||
+++ b/nptl/pthread_mutex_setprioceiling.c
|
|
||||||
@@ -27,9 +27,10 @@ int
|
|
||||||
pthread_mutex_setprioceiling (pthread_mutex_t *mutex, int prioceiling,
|
|
||||||
int *old_ceiling)
|
|
||||||
{
|
|
||||||
- /* The low bits of __kind aren't ever changed after pthread_mutex_init,
|
|
||||||
- so we don't need a lock yet. */
|
|
||||||
- if ((mutex->__data.__kind & PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0)
|
|
||||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
|
||||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
|
||||||
+ if ((atomic_load_relaxed (&(mutex->__data.__kind))
|
|
||||||
+ & PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0)
|
|
||||||
return EINVAL;
|
|
||||||
|
|
||||||
/* See __init_sched_fifo_prio. */
|
|
||||||
diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c
|
|
||||||
index 28237b0e58cfcaf5..888c12fe28b2ebfd 100644
|
|
||||||
--- a/nptl/pthread_mutex_timedlock.c
|
|
||||||
+++ b/nptl/pthread_mutex_timedlock.c
|
|
||||||
@@ -53,6 +53,8 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex,
|
|
||||||
/* We must not check ABSTIME here. If the thread does not block
|
|
||||||
abstime must not be checked for a valid value. */
|
|
||||||
|
|
||||||
+ /* See concurrency notes regarding mutex type which is loaded from __kind
|
|
||||||
+ in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */
|
|
||||||
switch (__builtin_expect (PTHREAD_MUTEX_TYPE_ELISION (mutex),
|
|
||||||
PTHREAD_MUTEX_TIMED_NP))
|
|
||||||
{
|
|
||||||
@@ -338,8 +340,14 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex,
|
|
||||||
case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
|
|
||||||
case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
|
|
||||||
{
|
|
||||||
- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
|
|
||||||
- int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
|
|
||||||
+ int kind, robust;
|
|
||||||
+ {
|
|
||||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
|
||||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
|
||||||
+ int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind));
|
|
||||||
+ kind = mutex_kind & PTHREAD_MUTEX_KIND_MASK_NP;
|
|
||||||
+ robust = mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
if (robust)
|
|
||||||
{
|
|
||||||
@@ -509,7 +517,10 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex,
|
|
||||||
case PTHREAD_MUTEX_PP_NORMAL_NP:
|
|
||||||
case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
|
|
||||||
{
|
|
||||||
- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
|
|
||||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
|
||||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
|
||||||
+ int kind = atomic_load_relaxed (&(mutex->__data.__kind))
|
|
||||||
+ & PTHREAD_MUTEX_KIND_MASK_NP;
|
|
||||||
|
|
||||||
oldval = mutex->__data.__lock;
|
|
||||||
|
|
||||||
diff --git a/nptl/pthread_mutex_trylock.c b/nptl/pthread_mutex_trylock.c
|
|
||||||
index 7de61f4f688c1537..fa90c1d1e6f5afc2 100644
|
|
||||||
--- a/nptl/pthread_mutex_trylock.c
|
|
||||||
+++ b/nptl/pthread_mutex_trylock.c
|
|
||||||
@@ -36,6 +36,8 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
|
|
||||||
int oldval;
|
|
||||||
pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
|
|
||||||
|
|
||||||
+ /* See concurrency notes regarding mutex type which is loaded from __kind
|
|
||||||
+ in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */
|
|
||||||
switch (__builtin_expect (PTHREAD_MUTEX_TYPE_ELISION (mutex),
|
|
||||||
PTHREAD_MUTEX_TIMED_NP))
|
|
||||||
{
|
|
||||||
@@ -199,8 +201,14 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
|
|
||||||
case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
|
|
||||||
case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
|
|
||||||
{
|
|
||||||
- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
|
|
||||||
- int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
|
|
||||||
+ int kind, robust;
|
|
||||||
+ {
|
|
||||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
|
||||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
|
||||||
+ int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind));
|
|
||||||
+ kind = mutex_kind & PTHREAD_MUTEX_KIND_MASK_NP;
|
|
||||||
+ robust = mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
if (robust)
|
|
||||||
/* Note: robust PI futexes are signaled by setting bit 0. */
|
|
||||||
@@ -325,7 +333,10 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
|
|
||||||
case PTHREAD_MUTEX_PP_NORMAL_NP:
|
|
||||||
case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
|
|
||||||
{
|
|
||||||
- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
|
|
||||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
|
||||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
|
||||||
+ int kind = atomic_load_relaxed (&(mutex->__data.__kind))
|
|
||||||
+ & PTHREAD_MUTEX_KIND_MASK_NP;
|
|
||||||
|
|
||||||
oldval = mutex->__data.__lock;
|
|
||||||
|
|
||||||
diff --git a/nptl/pthread_mutex_unlock.c b/nptl/pthread_mutex_unlock.c
|
|
||||||
index 9ea62943b7c6b159..68d04d53955584e5 100644
|
|
||||||
--- a/nptl/pthread_mutex_unlock.c
|
|
||||||
+++ b/nptl/pthread_mutex_unlock.c
|
|
||||||
@@ -35,6 +35,8 @@ int
|
|
||||||
attribute_hidden
|
|
||||||
__pthread_mutex_unlock_usercnt (pthread_mutex_t *mutex, int decr)
|
|
||||||
{
|
|
||||||
+ /* See concurrency notes regarding mutex type which is loaded from __kind
|
|
||||||
+ in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */
|
|
||||||
int type = PTHREAD_MUTEX_TYPE_ELISION (mutex);
|
|
||||||
if (__builtin_expect (type &
|
|
||||||
~(PTHREAD_MUTEX_KIND_MASK_NP|PTHREAD_MUTEX_ELISION_FLAGS_NP), 0))
|
|
||||||
@@ -222,13 +224,19 @@ __pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr)
|
|
||||||
/* If the previous owner died and the caller did not succeed in
|
|
||||||
making the state consistent, mark the mutex as unrecoverable
|
|
||||||
and make all waiters. */
|
|
||||||
- if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0
|
|
||||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
|
||||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
|
||||||
+ if ((atomic_load_relaxed (&(mutex->__data.__kind))
|
|
||||||
+ & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0
|
|
||||||
&& __builtin_expect (mutex->__data.__owner
|
|
||||||
== PTHREAD_MUTEX_INCONSISTENT, 0))
|
|
||||||
pi_notrecoverable:
|
|
||||||
newowner = PTHREAD_MUTEX_NOTRECOVERABLE;
|
|
||||||
|
|
||||||
- if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0)
|
|
||||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
|
||||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
|
||||||
+ if ((atomic_load_relaxed (&(mutex->__data.__kind))
|
|
||||||
+ & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0)
|
|
||||||
{
|
|
||||||
continue_pi_robust:
|
|
||||||
/* Remove mutex from the list.
|
|
||||||
@@ -251,7 +259,10 @@ __pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr)
|
|
||||||
/* Unlock. Load all necessary mutex data before releasing the mutex
|
|
||||||
to not violate the mutex destruction requirements (see
|
|
||||||
lll_unlock). */
|
|
||||||
- int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
|
|
||||||
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
|
|
||||||
+ in sysdeps/nptl/bits/thread-shared-types.h. */
|
|
||||||
+ int robust = atomic_load_relaxed (&(mutex->__data.__kind))
|
|
||||||
+ & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
|
|
||||||
private = (robust
|
|
||||||
? PTHREAD_ROBUST_MUTEX_PSHARED (mutex)
|
|
||||||
: PTHREAD_MUTEX_PSHARED (mutex));
|
|
||||||
diff --git a/nptl/tst-mutex10.c b/nptl/tst-mutex10.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000..e1113ca60a7c8db5
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/nptl/tst-mutex10.c
|
|
||||||
@@ -0,0 +1,109 @@
|
|
||||||
+/* Testing race while enabling lock elision.
|
|
||||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <http://www.gnu.org/licenses/>. */
|
|
||||||
+#include <stdio.h>
|
|
||||||
+#include <stdlib.h>
|
|
||||||
+#include <stdint.h>
|
|
||||||
+#include <pthread.h>
|
|
||||||
+#include <unistd.h>
|
|
||||||
+#include <getopt.h>
|
|
||||||
+#include <support/support.h>
|
|
||||||
+#include <support/xthread.h>
|
|
||||||
+
|
|
||||||
+static pthread_barrier_t barrier;
|
|
||||||
+static pthread_mutex_t mutex;
|
|
||||||
+static long long int iteration_count = 1000000;
|
|
||||||
+static unsigned int thread_count = 3;
|
|
||||||
+
|
|
||||||
+static void *
|
|
||||||
+thr_func (void *arg)
|
|
||||||
+{
|
|
||||||
+ long long int i;
|
|
||||||
+ for (i = 0; i < iteration_count; i++)
|
|
||||||
+ {
|
|
||||||
+ if ((uintptr_t) arg == 0)
|
|
||||||
+ {
|
|
||||||
+ xpthread_mutex_destroy (&mutex);
|
|
||||||
+ xpthread_mutex_init (&mutex, NULL);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ xpthread_barrier_wait (&barrier);
|
|
||||||
+
|
|
||||||
+ /* Test if enabling lock elision works if it is enabled concurrently.
|
|
||||||
+ There was a race in FORCE_ELISION macro which leads to either
|
|
||||||
+ pthread_mutex_destroy returning EBUSY as the owner was recorded
|
|
||||||
+ by pthread_mutex_lock - in "normal mutex" code path - but was not
|
|
||||||
+ resetted in pthread_mutex_unlock - in "elision" code path.
|
|
||||||
+ Or it leads to the assertion in nptl/pthread_mutex_lock.c:
|
|
||||||
+ assert (mutex->__data.__owner == 0);
|
|
||||||
+ Please ensure that the test is run with lock elision:
|
|
||||||
+ export GLIBC_TUNABLES=glibc.elision.enable=1 */
|
|
||||||
+ xpthread_mutex_lock (&mutex);
|
|
||||||
+ xpthread_mutex_unlock (&mutex);
|
|
||||||
+
|
|
||||||
+ xpthread_barrier_wait (&barrier);
|
|
||||||
+ }
|
|
||||||
+ return NULL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+do_test (void)
|
|
||||||
+{
|
|
||||||
+ unsigned int i;
|
|
||||||
+ printf ("Starting %d threads to run %lld iterations.\n",
|
|
||||||
+ thread_count, iteration_count);
|
|
||||||
+
|
|
||||||
+ pthread_t *threads = xmalloc (thread_count * sizeof (pthread_t));
|
|
||||||
+ xpthread_barrier_init (&barrier, NULL, thread_count);
|
|
||||||
+ xpthread_mutex_init (&mutex, NULL);
|
|
||||||
+
|
|
||||||
+ for (i = 0; i < thread_count; i++)
|
|
||||||
+ threads[i] = xpthread_create (NULL, thr_func, (void *) (uintptr_t) i);
|
|
||||||
+
|
|
||||||
+ for (i = 0; i < thread_count; i++)
|
|
||||||
+ xpthread_join (threads[i]);
|
|
||||||
+
|
|
||||||
+ xpthread_barrier_destroy (&barrier);
|
|
||||||
+ free (threads);
|
|
||||||
+
|
|
||||||
+ return EXIT_SUCCESS;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#define OPT_ITERATIONS 10000
|
|
||||||
+#define OPT_THREADS 10001
|
|
||||||
+#define CMDLINE_OPTIONS \
|
|
||||||
+ { "iterations", required_argument, NULL, OPT_ITERATIONS }, \
|
|
||||||
+ { "threads", required_argument, NULL, OPT_THREADS },
|
|
||||||
+static void
|
|
||||||
+cmdline_process (int c)
|
|
||||||
+{
|
|
||||||
+ long long int arg = strtoll (optarg, NULL, 0);
|
|
||||||
+ switch (c)
|
|
||||||
+ {
|
|
||||||
+ case OPT_ITERATIONS:
|
|
||||||
+ if (arg > 0)
|
|
||||||
+ iteration_count = arg;
|
|
||||||
+ break;
|
|
||||||
+ case OPT_THREADS:
|
|
||||||
+ if (arg > 0 && arg < 100)
|
|
||||||
+ thread_count = arg;
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+#define CMDLINE_PROCESS cmdline_process
|
|
||||||
+#define TIMEOUT 50
|
|
||||||
+#include <support/test-driver.c>
|
|
||||||
diff --git a/sysdeps/nptl/bits/thread-shared-types.h b/sysdeps/nptl/bits/thread-shared-types.h
|
|
||||||
index 1e2092a05d5610f7..05c94e7a710c0eb9 100644
|
|
||||||
--- a/sysdeps/nptl/bits/thread-shared-types.h
|
|
||||||
+++ b/sysdeps/nptl/bits/thread-shared-types.h
|
|
||||||
@@ -124,7 +124,27 @@ struct __pthread_mutex_s
|
|
||||||
unsigned int __nusers;
|
|
||||||
#endif
|
|
||||||
/* KIND must stay at this position in the structure to maintain
|
|
||||||
- binary compatibility with static initializers. */
|
|
||||||
+ binary compatibility with static initializers.
|
|
||||||
+
|
|
||||||
+ Concurrency notes:
|
|
||||||
+ The __kind of a mutex is initialized either by the static
|
|
||||||
+ PTHREAD_MUTEX_INITIALIZER or by a call to pthread_mutex_init.
|
|
||||||
+
|
|
||||||
+ After a mutex has been initialized, the __kind of a mutex is usually not
|
|
||||||
+ changed. BUT it can be set to -1 in pthread_mutex_destroy or elision can
|
|
||||||
+ be enabled. This is done concurrently in the pthread_mutex_*lock functions
|
|
||||||
+ by using the macro FORCE_ELISION. This macro is only defined for
|
|
||||||
+ architectures which supports lock elision.
|
|
||||||
+
|
|
||||||
+ For elision, there are the flags PTHREAD_MUTEX_ELISION_NP and
|
|
||||||
+ PTHREAD_MUTEX_NO_ELISION_NP which can be set in addition to the already set
|
|
||||||
+ type of a mutex.
|
|
||||||
+ Before a mutex is initialized, only PTHREAD_MUTEX_NO_ELISION_NP can be set
|
|
||||||
+ with pthread_mutexattr_settype.
|
|
||||||
+ After a mutex has been initialized, the functions pthread_mutex_*lock can
|
|
||||||
+ enable elision - if the mutex-type and the machine supports it - by setting
|
|
||||||
+ the flag PTHREAD_MUTEX_ELISION_NP. This is done concurrently. Afterwards
|
|
||||||
+ the lock / unlock functions are using specific elision code-paths. */
|
|
||||||
int __kind;
|
|
||||||
__PTHREAD_COMPAT_PADDING_MID
|
|
||||||
#if __PTHREAD_MUTEX_NUSERS_AFTER_KIND
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/force-elision.h b/sysdeps/unix/sysv/linux/powerpc/force-elision.h
|
|
||||||
index fe5d6ceade2bad36..d8f5a4b1c7713bd4 100644
|
|
||||||
--- a/sysdeps/unix/sysv/linux/powerpc/force-elision.h
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/powerpc/force-elision.h
|
|
||||||
@@ -18,9 +18,45 @@
|
|
||||||
|
|
||||||
/* Automatically enable elision for existing user lock kinds. */
|
|
||||||
#define FORCE_ELISION(m, s) \
|
|
||||||
- if (__pthread_force_elision \
|
|
||||||
- && (m->__data.__kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \
|
|
||||||
+ if (__pthread_force_elision) \
|
|
||||||
{ \
|
|
||||||
- mutex->__data.__kind |= PTHREAD_MUTEX_ELISION_NP; \
|
|
||||||
- s; \
|
|
||||||
+ /* See concurrency notes regarding __kind in \
|
|
||||||
+ struct __pthread_mutex_s in \
|
|
||||||
+ sysdeps/nptl/bits/thread-shared-types.h. \
|
|
||||||
+ \
|
|
||||||
+ There are the following cases for the kind of a mutex \
|
|
||||||
+ (The mask PTHREAD_MUTEX_ELISION_FLAGS_NP covers the flags \
|
|
||||||
+ PTHREAD_MUTEX_ELISION_NP and PTHREAD_MUTEX_NO_ELISION_NP where \
|
|
||||||
+ only one of both flags can be set): \
|
|
||||||
+ - both flags are not set: \
|
|
||||||
+ This is the first lock operation for this mutex. Enable \
|
|
||||||
+ elision as it is not enabled so far. \
|
|
||||||
+ Note: It can happen that multiple threads are calling e.g. \
|
|
||||||
+ pthread_mutex_lock at the same time as the first lock \
|
|
||||||
+ operation for this mutex. Then elision is enabled for this \
|
|
||||||
+ mutex by multiple threads. Storing with relaxed MO is enough \
|
|
||||||
+ as all threads will store the same new value for the kind of \
|
|
||||||
+ the mutex. But we have to ensure that we always use the \
|
|
||||||
+ elision path regardless if this thread has enabled elision or \
|
|
||||||
+ another one. \
|
|
||||||
+ \
|
|
||||||
+ - PTHREAD_MUTEX_ELISION_NP flag is set: \
|
|
||||||
+ Elision was already enabled for this mutex by a previous lock \
|
|
||||||
+ operation. See case above. Just use the elision path. \
|
|
||||||
+ \
|
|
||||||
+ - PTHREAD_MUTEX_NO_ELISION_NP flag is set: \
|
|
||||||
+ Elision was explicitly disabled by pthread_mutexattr_settype. \
|
|
||||||
+ Do not use the elision path. \
|
|
||||||
+ Note: The flag PTHREAD_MUTEX_NO_ELISION_NP will never be \
|
|
||||||
+ changed after mutex initialization. */ \
|
|
||||||
+ int mutex_kind = atomic_load_relaxed (&((m)->__data.__kind)); \
|
|
||||||
+ if ((mutex_kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \
|
|
||||||
+ { \
|
|
||||||
+ mutex_kind |= PTHREAD_MUTEX_ELISION_NP; \
|
|
||||||
+ atomic_store_relaxed (&((m)->__data.__kind), mutex_kind); \
|
|
||||||
+ } \
|
|
||||||
+ if ((mutex_kind & PTHREAD_MUTEX_ELISION_NP) != 0) \
|
|
||||||
+ { \
|
|
||||||
+ s; \
|
|
||||||
+ } \
|
|
||||||
}
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/s390/force-elision.h b/sysdeps/unix/sysv/linux/s390/force-elision.h
|
|
||||||
index d8a1b9972f739cfe..71f32367dd6b6489 100644
|
|
||||||
--- a/sysdeps/unix/sysv/linux/s390/force-elision.h
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/s390/force-elision.h
|
|
||||||
@@ -18,9 +18,45 @@
|
|
||||||
|
|
||||||
/* Automatically enable elision for existing user lock kinds. */
|
|
||||||
#define FORCE_ELISION(m, s) \
|
|
||||||
- if (__pthread_force_elision \
|
|
||||||
- && (m->__data.__kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \
|
|
||||||
+ if (__pthread_force_elision) \
|
|
||||||
{ \
|
|
||||||
- mutex->__data.__kind |= PTHREAD_MUTEX_ELISION_NP; \
|
|
||||||
- s; \
|
|
||||||
+ /* See concurrency notes regarding __kind in \
|
|
||||||
+ struct __pthread_mutex_s in \
|
|
||||||
+ sysdeps/nptl/bits/thread-shared-types.h. \
|
|
||||||
+ \
|
|
||||||
+ There are the following cases for the kind of a mutex \
|
|
||||||
+ (The mask PTHREAD_MUTEX_ELISION_FLAGS_NP covers the flags \
|
|
||||||
+ PTHREAD_MUTEX_ELISION_NP and PTHREAD_MUTEX_NO_ELISION_NP where \
|
|
||||||
+ only one of both flags can be set): \
|
|
||||||
+ - both flags are not set: \
|
|
||||||
+ This is the first lock operation for this mutex. Enable \
|
|
||||||
+ elision as it is not enabled so far. \
|
|
||||||
+ Note: It can happen that multiple threads are calling e.g. \
|
|
||||||
+ pthread_mutex_lock at the same time as the first lock \
|
|
||||||
+ operation for this mutex. Then elision is enabled for this \
|
|
||||||
+ mutex by multiple threads. Storing with relaxed MO is enough \
|
|
||||||
+ as all threads will store the same new value for the kind of \
|
|
||||||
+ the mutex. But we have to ensure that we always use the \
|
|
||||||
+ elision path regardless if this thread has enabled elision or \
|
|
||||||
+ another one. \
|
|
||||||
+ \
|
|
||||||
+ - PTHREAD_MUTEX_ELISION_NP flag is set: \
|
|
||||||
+ Elision was already enabled for this mutex by a previous lock \
|
|
||||||
+ operation. See case above. Just use the elision path. \
|
|
||||||
+ \
|
|
||||||
+ - PTHREAD_MUTEX_NO_ELISION_NP flag is set: \
|
|
||||||
+ Elision was explicitly disabled by pthread_mutexattr_settype. \
|
|
||||||
+ Do not use the elision path. \
|
|
||||||
+ Note: The flag PTHREAD_MUTEX_NO_ELISION_NP will never be \
|
|
||||||
+ changed after mutex initialization. */ \
|
|
||||||
+ int mutex_kind = atomic_load_relaxed (&((m)->__data.__kind)); \
|
|
||||||
+ if ((mutex_kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \
|
|
||||||
+ { \
|
|
||||||
+ mutex_kind |= PTHREAD_MUTEX_ELISION_NP; \
|
|
||||||
+ atomic_store_relaxed (&((m)->__data.__kind), mutex_kind); \
|
|
||||||
+ } \
|
|
||||||
+ if ((mutex_kind & PTHREAD_MUTEX_ELISION_NP) != 0) \
|
|
||||||
+ { \
|
|
||||||
+ s; \
|
|
||||||
+ } \
|
|
||||||
}
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/x86/force-elision.h b/sysdeps/unix/sysv/linux/x86/force-elision.h
|
|
||||||
index dd659c908f3046c1..61282d6678d89787 100644
|
|
||||||
--- a/sysdeps/unix/sysv/linux/x86/force-elision.h
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/x86/force-elision.h
|
|
||||||
@@ -18,9 +18,45 @@
|
|
||||||
|
|
||||||
/* Automatically enable elision for existing user lock kinds. */
|
|
||||||
#define FORCE_ELISION(m, s) \
|
|
||||||
- if (__pthread_force_elision \
|
|
||||||
- && (m->__data.__kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \
|
|
||||||
+ if (__pthread_force_elision) \
|
|
||||||
{ \
|
|
||||||
- mutex->__data.__kind |= PTHREAD_MUTEX_ELISION_NP; \
|
|
||||||
- s; \
|
|
||||||
+ /* See concurrency notes regarding __kind in \
|
|
||||||
+ struct __pthread_mutex_s in \
|
|
||||||
+ sysdeps/nptl/bits/thread-shared-types.h. \
|
|
||||||
+ \
|
|
||||||
+ There are the following cases for the kind of a mutex \
|
|
||||||
+ (The mask PTHREAD_MUTEX_ELISION_FLAGS_NP covers the flags \
|
|
||||||
+ PTHREAD_MUTEX_ELISION_NP and PTHREAD_MUTEX_NO_ELISION_NP where \
|
|
||||||
+ only one of both flags can be set): \
|
|
||||||
+ - both flags are not set: \
|
|
||||||
+ This is the first lock operation for this mutex. Enable \
|
|
||||||
+ elision as it is not enabled so far. \
|
|
||||||
+ Note: It can happen that multiple threads are calling e.g. \
|
|
||||||
+ pthread_mutex_lock at the same time as the first lock \
|
|
||||||
+ operation for this mutex. Then elision is enabled for this \
|
|
||||||
+ mutex by multiple threads. Storing with relaxed MO is enough \
|
|
||||||
+ as all threads will store the same new value for the kind of \
|
|
||||||
+ the mutex. But we have to ensure that we always use the \
|
|
||||||
+ elision path regardless if this thread has enabled elision or \
|
|
||||||
+ another one. \
|
|
||||||
+ \
|
|
||||||
+ - PTHREAD_MUTEX_ELISION_NP flag is set: \
|
|
||||||
+ Elision was already enabled for this mutex by a previous lock \
|
|
||||||
+ operation. See case above. Just use the elision path. \
|
|
||||||
+ \
|
|
||||||
+ - PTHREAD_MUTEX_NO_ELISION_NP flag is set: \
|
|
||||||
+ Elision was explicitly disabled by pthread_mutexattr_settype. \
|
|
||||||
+ Do not use the elision path. \
|
|
||||||
+ Note: The flag PTHREAD_MUTEX_NO_ELISION_NP will never be \
|
|
||||||
+ changed after mutex initialization. */ \
|
|
||||||
+ int mutex_kind = atomic_load_relaxed (&((m)->__data.__kind)); \
|
|
||||||
+ if ((mutex_kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \
|
|
||||||
+ { \
|
|
||||||
+ mutex_kind |= PTHREAD_MUTEX_ELISION_NP; \
|
|
||||||
+ atomic_store_relaxed (&((m)->__data.__kind), mutex_kind); \
|
|
||||||
+ } \
|
|
||||||
+ if ((mutex_kind & PTHREAD_MUTEX_ELISION_NP) != 0) \
|
|
||||||
+ { \
|
|
||||||
+ s; \
|
|
||||||
+ } \
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
commit bd3b0fbae33a9a4cc5e2daf049443d5cf03d4251
|
|
||||||
Author: Andreas Schwab <schwab@suse.de>
|
|
||||||
Date: Mon Nov 5 12:47:30 2018 +0100
|
|
||||||
|
|
||||||
libanl: properly cleanup if first helper thread creation failed (bug 22927)
|
|
||||||
|
|
||||||
diff --git a/resolv/gai_misc.c b/resolv/gai_misc.c
|
|
||||||
index e7c3b63cc5725b4f..80a2cff8353fcb6c 100644
|
|
||||||
--- a/resolv/gai_misc.c
|
|
||||||
+++ b/resolv/gai_misc.c
|
|
||||||
@@ -261,8 +261,11 @@ __gai_enqueue_request (struct gaicb *gaicbp)
|
|
||||||
/* We cannot create a thread in the moment and there is
|
|
||||||
also no thread running. This is a problem. `errno' is
|
|
||||||
set to EAGAIN if this is only a temporary problem. */
|
|
||||||
- assert (lastp->next == newp);
|
|
||||||
- lastp->next = NULL;
|
|
||||||
+ assert (requests == newp || lastp->next == newp);
|
|
||||||
+ if (lastp != NULL)
|
|
||||||
+ lastp->next = NULL;
|
|
||||||
+ else
|
|
||||||
+ requests = NULL;
|
|
||||||
requests_tail = lastp;
|
|
||||||
|
|
||||||
newp->next = freelist;
|
|
@ -1,48 +0,0 @@
|
|||||||
commit 17b26500f9bb926d85e86821d014f7c1bb88043c
|
|
||||||
Author: Joseph Myers <joseph@codesourcery.com>
|
|
||||||
Date: Mon Aug 13 21:35:27 2018 +0000
|
|
||||||
|
|
||||||
Update syscall-names.list for Linux 4.18.
|
|
||||||
|
|
||||||
This patch updates sysdeps/unix/sysv/linux/syscall-names.list for
|
|
||||||
Linux 4.18. The io_pgetevents and rseq syscalls are added to the
|
|
||||||
kernel on various architectures, so need to be mentioned in this file.
|
|
||||||
|
|
||||||
Tested with build-many-glibcs.py.
|
|
||||||
|
|
||||||
* sysdeps/unix/sysv/linux/syscall-names.list: Update kernel
|
|
||||||
version to 4.18.
|
|
||||||
(io_pgetevents): New syscall.
|
|
||||||
(rseq): Likewise.
|
|
||||||
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
|
|
||||||
index 5306d538e6448163..9982a6334d46ae62 100644
|
|
||||||
--- a/sysdeps/unix/sysv/linux/syscall-names.list
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
|
|
||||||
@@ -22,8 +22,8 @@
|
|
||||||
# names are only used if the installed kernel headers also provide
|
|
||||||
# them.
|
|
||||||
|
|
||||||
-# The list of system calls is current as of Linux 4.17.
|
|
||||||
-kernel 4.17
|
|
||||||
+# The list of system calls is current as of Linux 4.18.
|
|
||||||
+kernel 4.18
|
|
||||||
|
|
||||||
FAST_atomic_update
|
|
||||||
FAST_cmpxchg
|
|
||||||
@@ -186,6 +186,7 @@ inotify_rm_watch
|
|
||||||
io_cancel
|
|
||||||
io_destroy
|
|
||||||
io_getevents
|
|
||||||
+io_pgetevents
|
|
||||||
io_setup
|
|
||||||
io_submit
|
|
||||||
ioctl
|
|
||||||
@@ -431,6 +432,7 @@ renameat2
|
|
||||||
request_key
|
|
||||||
restart_syscall
|
|
||||||
rmdir
|
|
||||||
+rseq
|
|
||||||
rt_sigaction
|
|
||||||
rt_sigpending
|
|
||||||
rt_sigprocmask
|
|
@ -1,30 +0,0 @@
|
|||||||
commit 029ad711b8ad4cf0e5d98e0c138a35a23a376a74
|
|
||||||
Author: Joseph Myers <joseph@codesourcery.com>
|
|
||||||
Date: Mon Oct 22 23:26:37 2018 +0000
|
|
||||||
|
|
||||||
Update kernel version in syscall-names.list to 4.19.
|
|
||||||
|
|
||||||
Linux 4.19 does not add any new syscalls (some existing ones are added
|
|
||||||
to more architectures); this patch updates the version number in
|
|
||||||
syscall-names.list to reflect that it's still current for 4.19.
|
|
||||||
|
|
||||||
Tested with build-many-glibcs.py.
|
|
||||||
|
|
||||||
* sysdeps/unix/sysv/linux/syscall-names.list: Update kernel
|
|
||||||
version to 4.19.
|
|
||||||
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
|
|
||||||
index 9982a6334d46ae62..f88001c9c38d5fc7 100644
|
|
||||||
--- a/sysdeps/unix/sysv/linux/syscall-names.list
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
|
|
||||||
@@ -22,8 +22,8 @@
|
|
||||||
# names are only used if the installed kernel headers also provide
|
|
||||||
# them.
|
|
||||||
|
|
||||||
-# The list of system calls is current as of Linux 4.18.
|
|
||||||
-kernel 4.18
|
|
||||||
+# The list of system calls is current as of Linux 4.19.
|
|
||||||
+kernel 4.19
|
|
||||||
|
|
||||||
FAST_atomic_update
|
|
||||||
FAST_cmpxchg
|
|
@ -1,127 +0,0 @@
|
|||||||
commit 745664bd798ec8fd50438605948eea594179fba1
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Tue Aug 28 13:19:27 2018 +0200
|
|
||||||
|
|
||||||
nscd: Fix use-after-free in addgetnetgrentX [BZ #23520]
|
|
||||||
|
|
||||||
addinnetgrX may use the heap-allocated buffer, so free the buffer
|
|
||||||
in this function.
|
|
||||||
|
|
||||||
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
|
|
||||||
index 2b35389cc816c3c8..87059fb28042f0a5 100644
|
|
||||||
--- a/nscd/netgroupcache.c
|
|
||||||
+++ b/nscd/netgroupcache.c
|
|
||||||
@@ -113,7 +113,8 @@ do_notfound (struct database_dyn *db, int fd, request_header *req,
|
|
||||||
static time_t
|
|
||||||
addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
|
||||||
const char *key, uid_t uid, struct hashentry *he,
|
|
||||||
- struct datahead *dh, struct dataset **resultp)
|
|
||||||
+ struct datahead *dh, struct dataset **resultp,
|
|
||||||
+ void **tofreep)
|
|
||||||
{
|
|
||||||
if (__glibc_unlikely (debug_level > 0))
|
|
||||||
{
|
|
||||||
@@ -139,6 +140,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
|
||||||
size_t group_len = strlen (key) + 1;
|
|
||||||
struct name_list *first_needed
|
|
||||||
= alloca (sizeof (struct name_list) + group_len);
|
|
||||||
+ *tofreep = NULL;
|
|
||||||
|
|
||||||
if (netgroup_database == NULL
|
|
||||||
&& __nss_database_lookup ("netgroup", NULL, NULL, &netgroup_database))
|
|
||||||
@@ -151,6 +153,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
|
||||||
|
|
||||||
memset (&data, '\0', sizeof (data));
|
|
||||||
buffer = xmalloc (buflen);
|
|
||||||
+ *tofreep = buffer;
|
|
||||||
first_needed->next = first_needed;
|
|
||||||
memcpy (first_needed->name, key, group_len);
|
|
||||||
data.needed_groups = first_needed;
|
|
||||||
@@ -439,8 +442,6 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
- free (buffer);
|
|
||||||
-
|
|
||||||
*resultp = dataset;
|
|
||||||
|
|
||||||
return timeout;
|
|
||||||
@@ -477,8 +478,12 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
|
||||||
group, group_len,
|
|
||||||
db, uid);
|
|
||||||
time_t timeout;
|
|
||||||
+ void *tofree;
|
|
||||||
if (result != NULL)
|
|
||||||
- timeout = result->head.timeout;
|
|
||||||
+ {
|
|
||||||
+ timeout = result->head.timeout;
|
|
||||||
+ tofree = NULL;
|
|
||||||
+ }
|
|
||||||
else
|
|
||||||
{
|
|
||||||
request_header req_get =
|
|
||||||
@@ -487,7 +492,7 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
|
||||||
.key_len = group_len
|
|
||||||
};
|
|
||||||
timeout = addgetnetgrentX (db, -1, &req_get, group, uid, NULL, NULL,
|
|
||||||
- &result);
|
|
||||||
+ &result, &tofree);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct indataset
|
|
||||||
@@ -560,7 +565,7 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
|
||||||
++dh->nreloads;
|
|
||||||
if (cacheable)
|
|
||||||
pthread_rwlock_unlock (&db->lock);
|
|
||||||
- return timeout;
|
|
||||||
+ goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (he == NULL)
|
|
||||||
@@ -596,17 +601,30 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
|
||||||
dh->usable = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ out:
|
|
||||||
+ free (tofree);
|
|
||||||
return timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
+static time_t
|
|
||||||
+addgetnetgrentX_ignore (struct database_dyn *db, int fd, request_header *req,
|
|
||||||
+ const char *key, uid_t uid, struct hashentry *he,
|
|
||||||
+ struct datahead *dh)
|
|
||||||
+{
|
|
||||||
+ struct dataset *ignore;
|
|
||||||
+ void *tofree;
|
|
||||||
+ time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh,
|
|
||||||
+ &ignore, &tofree);
|
|
||||||
+ free (tofree);
|
|
||||||
+ return timeout;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void
|
|
||||||
addgetnetgrent (struct database_dyn *db, int fd, request_header *req,
|
|
||||||
void *key, uid_t uid)
|
|
||||||
{
|
|
||||||
- struct dataset *ignore;
|
|
||||||
-
|
|
||||||
- addgetnetgrentX (db, fd, req, key, uid, NULL, NULL, &ignore);
|
|
||||||
+ addgetnetgrentX_ignore (db, fd, req, key, uid, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -619,10 +637,8 @@ readdgetnetgrent (struct database_dyn *db, struct hashentry *he,
|
|
||||||
.type = GETNETGRENT,
|
|
||||||
.key_len = he->len
|
|
||||||
};
|
|
||||||
- struct dataset *ignore;
|
|
||||||
-
|
|
||||||
- return addgetnetgrentX (db, -1, &req, db->data + he->key, he->owner, he, dh,
|
|
||||||
- &ignore);
|
|
||||||
+ return addgetnetgrentX_ignore
|
|
||||||
+ (db, -1, &req, db->data + he->key, he->owner, he, dh);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,234 +0,0 @@
|
|||||||
commit a6e8926f8d49a213a9abb1a61f6af964f612ab7f
|
|
||||||
Author: Paul Pluzhnikov <ppluzhnikov@google.com>
|
|
||||||
Date: Fri Aug 31 18:04:32 2018 -0700
|
|
||||||
|
|
||||||
[BZ #20271] Add newlines in __libc_fatal calls.
|
|
||||||
|
|
||||||
diff --git a/grp/initgroups.c b/grp/initgroups.c
|
|
||||||
index f056fbf5aa6aa14c..93e7f5814da6286d 100644
|
|
||||||
--- a/grp/initgroups.c
|
|
||||||
+++ b/grp/initgroups.c
|
|
||||||
@@ -128,7 +128,7 @@ internal_getgrouplist (const char *user, gid_t group, long int *size,
|
|
||||||
|
|
||||||
/* This is really only for debugging. */
|
|
||||||
if (NSS_STATUS_TRYAGAIN > status || status > NSS_STATUS_RETURN)
|
|
||||||
- __libc_fatal ("illegal status in internal_getgrouplist");
|
|
||||||
+ __libc_fatal ("Illegal status in internal_getgrouplist.\n");
|
|
||||||
|
|
||||||
/* For compatibility reason we will continue to look for more
|
|
||||||
entries using the next service even though data has already
|
|
||||||
diff --git a/include/stdio.h b/include/stdio.h
|
|
||||||
index 9162d4e24717e31a..7a5c09089fc4d348 100644
|
|
||||||
--- a/include/stdio.h
|
|
||||||
+++ b/include/stdio.h
|
|
||||||
@@ -98,7 +98,8 @@ enum __libc_message_action
|
|
||||||
do_backtrace = 1 << 1 /* Backtrace. */
|
|
||||||
};
|
|
||||||
|
|
||||||
-/* Print out MESSAGE on the error output and abort. */
|
|
||||||
+/* Print out MESSAGE (which should end with a newline) on the error output
|
|
||||||
+ and abort. */
|
|
||||||
extern void __libc_fatal (const char *__message)
|
|
||||||
__attribute__ ((__noreturn__));
|
|
||||||
extern void __libc_message (enum __libc_message_action action,
|
|
||||||
diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
|
|
||||||
index 3e1105418210288e..ebf07ca82d87de7d 100644
|
|
||||||
--- a/nptl/pthread_cond_wait.c
|
|
||||||
+++ b/nptl/pthread_cond_wait.c
|
|
||||||
@@ -516,7 +516,7 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
|
||||||
struct timespec rt;
|
|
||||||
if (__clock_gettime (CLOCK_MONOTONIC, &rt) != 0)
|
|
||||||
__libc_fatal ("clock_gettime does not support "
|
|
||||||
- "CLOCK_MONOTONIC");
|
|
||||||
+ "CLOCK_MONOTONIC\n");
|
|
||||||
/* Convert the absolute timeout value to a relative
|
|
||||||
timeout. */
|
|
||||||
rt.tv_sec = abstime->tv_sec - rt.tv_sec;
|
|
||||||
diff --git a/nscd/initgrcache.c b/nscd/initgrcache.c
|
|
||||||
index 2c74951f579f4afd..4764f14a45f68e0a 100644
|
|
||||||
--- a/nscd/initgrcache.c
|
|
||||||
+++ b/nscd/initgrcache.c
|
|
||||||
@@ -159,7 +159,7 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req,
|
|
||||||
|
|
||||||
/* This is really only for debugging. */
|
|
||||||
if (NSS_STATUS_TRYAGAIN > status || status > NSS_STATUS_RETURN)
|
|
||||||
- __libc_fatal ("illegal status in internal_getgrouplist");
|
|
||||||
+ __libc_fatal ("Illegal status in internal_getgrouplist.\n");
|
|
||||||
|
|
||||||
any_success |= status == NSS_STATUS_SUCCESS;
|
|
||||||
|
|
||||||
diff --git a/nss/nsswitch.c b/nss/nsswitch.c
|
|
||||||
index ee46f24424bc1ca2..3c48b4b85e881cdb 100644
|
|
||||||
--- a/nss/nsswitch.c
|
|
||||||
+++ b/nss/nsswitch.c
|
|
||||||
@@ -235,7 +235,7 @@ __nss_next2 (service_user **ni, const char *fct_name, const char *fct2_name,
|
|
||||||
/* This is really only for debugging. */
|
|
||||||
if (__builtin_expect (NSS_STATUS_TRYAGAIN > status
|
|
||||||
|| status > NSS_STATUS_RETURN, 0))
|
|
||||||
- __libc_fatal ("illegal status in __nss_next");
|
|
||||||
+ __libc_fatal ("Illegal status in __nss_next.\n");
|
|
||||||
|
|
||||||
if (nss_next_action (*ni, status) == NSS_ACTION_RETURN)
|
|
||||||
return 1;
|
|
||||||
diff --git a/sysdeps/aarch64/dl-irel.h b/sysdeps/aarch64/dl-irel.h
|
|
||||||
index 5889ee187b7a1eaf..bef71ed0f31a6387 100644
|
|
||||||
--- a/sysdeps/aarch64/dl-irel.h
|
|
||||||
+++ b/sysdeps/aarch64/dl-irel.h
|
|
||||||
@@ -47,7 +47,7 @@ elf_irela (const ElfW(Rela) *reloc)
|
|
||||||
*reloc_addr = value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
- __libc_fatal ("unexpected reloc type in static binary");
|
|
||||||
+ __libc_fatal ("Unexpected reloc type in static binary.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
diff --git a/sysdeps/arm/dl-irel.h b/sysdeps/arm/dl-irel.h
|
|
||||||
index a7b6456075659baf..be6eb7743eb5f08d 100644
|
|
||||||
--- a/sysdeps/arm/dl-irel.h
|
|
||||||
+++ b/sysdeps/arm/dl-irel.h
|
|
||||||
@@ -46,7 +46,7 @@ elf_irel (const Elf32_Rel *reloc)
|
|
||||||
*reloc_addr = value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
- __libc_fatal ("unexpected reloc type in static binary");
|
|
||||||
+ __libc_fatal ("Unexpected reloc type in static binary.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* dl-irel.h */
|
|
||||||
diff --git a/sysdeps/generic/unwind-dw2.c b/sysdeps/generic/unwind-dw2.c
|
|
||||||
index 082609b34a3f773b..724c16a7f0bf465b 100644
|
|
||||||
--- a/sysdeps/generic/unwind-dw2.c
|
|
||||||
+++ b/sysdeps/generic/unwind-dw2.c
|
|
||||||
@@ -843,7 +843,7 @@ execute_cfa_program (const unsigned char *insn_ptr,
|
|
||||||
struct frame_state_reg_info *old_rs = fs->regs.prev;
|
|
||||||
#ifdef _LIBC
|
|
||||||
if (old_rs == NULL)
|
|
||||||
- __libc_fatal ("invalid DWARF unwind data");
|
|
||||||
+ __libc_fatal ("Invalid DWARF unwind data.\n");
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
diff --git a/sysdeps/i386/dl-irel.h b/sysdeps/i386/dl-irel.h
|
|
||||||
index 55303180c7aca495..bcaf0668acf8e2f2 100644
|
|
||||||
--- a/sysdeps/i386/dl-irel.h
|
|
||||||
+++ b/sysdeps/i386/dl-irel.h
|
|
||||||
@@ -45,7 +45,7 @@ elf_irel (const Elf32_Rel *reloc)
|
|
||||||
*reloc_addr = value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
- __libc_fatal ("unexpected reloc type in static binary");
|
|
||||||
+ __libc_fatal ("Unexpected reloc type in static binary.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* dl-irel.h */
|
|
||||||
diff --git a/sysdeps/nptl/futex-internal.h b/sysdeps/nptl/futex-internal.h
|
|
||||||
index 1a5624789d4ab117..6fd27f0df6c27b69 100644
|
|
||||||
--- a/sysdeps/nptl/futex-internal.h
|
|
||||||
+++ b/sysdeps/nptl/futex-internal.h
|
|
||||||
@@ -197,7 +197,7 @@ futex_wake (unsigned int* futex_word, int processes_to_wake, int private);
|
|
||||||
static __always_inline __attribute__ ((__noreturn__)) void
|
|
||||||
futex_fatal_error (void)
|
|
||||||
{
|
|
||||||
- __libc_fatal ("The futex facility returned an unexpected error code.");
|
|
||||||
+ __libc_fatal ("The futex facility returned an unexpected error code.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* futex-internal.h */
|
|
||||||
diff --git a/sysdeps/powerpc/powerpc32/dl-irel.h b/sysdeps/powerpc/powerpc32/dl-irel.h
|
|
||||||
index a7368b25829618cb..61d0e4cf61ec45d3 100644
|
|
||||||
--- a/sysdeps/powerpc/powerpc32/dl-irel.h
|
|
||||||
+++ b/sysdeps/powerpc/powerpc32/dl-irel.h
|
|
||||||
@@ -46,7 +46,7 @@ elf_irela (const Elf32_Rela *reloc)
|
|
||||||
*reloc_addr = value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
- __libc_fatal ("unexpected reloc type in static binary");
|
|
||||||
+ __libc_fatal ("Unexpected reloc type in static binary.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* dl-irel.h */
|
|
||||||
diff --git a/sysdeps/powerpc/powerpc64/dl-irel.h b/sysdeps/powerpc/powerpc64/dl-irel.h
|
|
||||||
index ab13c04358868270..2fd0ee8a86e85ba0 100644
|
|
||||||
--- a/sysdeps/powerpc/powerpc64/dl-irel.h
|
|
||||||
+++ b/sysdeps/powerpc/powerpc64/dl-irel.h
|
|
||||||
@@ -57,7 +57,7 @@ elf_irela (const Elf64_Rela *reloc)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
- __libc_fatal ("unexpected reloc type in static binary");
|
|
||||||
+ __libc_fatal ("Unexpected reloc type in static binary.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* dl-irel.h */
|
|
||||||
diff --git a/sysdeps/s390/dl-irel.h b/sysdeps/s390/dl-irel.h
|
|
||||||
index d8ba7ba42709f45c..ecb24f0a9be0daa7 100644
|
|
||||||
--- a/sysdeps/s390/dl-irel.h
|
|
||||||
+++ b/sysdeps/s390/dl-irel.h
|
|
||||||
@@ -46,7 +46,7 @@ elf_irela (const ElfW(Rela) *reloc)
|
|
||||||
*reloc_addr = value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
- __libc_fatal ("unexpected reloc type in static binary");
|
|
||||||
+ __libc_fatal ("Unexpected reloc type in static binary.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* dl-irel.h */
|
|
||||||
diff --git a/sysdeps/sparc/sparc32/dl-irel.h b/sysdeps/sparc/sparc32/dl-irel.h
|
|
||||||
index ffca36864f24d1fb..cf47cda8345b1a39 100644
|
|
||||||
--- a/sysdeps/sparc/sparc32/dl-irel.h
|
|
||||||
+++ b/sysdeps/sparc/sparc32/dl-irel.h
|
|
||||||
@@ -56,7 +56,7 @@ elf_irela (const Elf32_Rela *reloc)
|
|
||||||
else if (r_type == R_SPARC_NONE)
|
|
||||||
;
|
|
||||||
else
|
|
||||||
- __libc_fatal ("unexpected reloc type in static binary");
|
|
||||||
+ __libc_fatal ("Unexpected reloc type in static binary.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* dl-irel.h */
|
|
||||||
diff --git a/sysdeps/sparc/sparc64/dl-irel.h b/sysdeps/sparc/sparc64/dl-irel.h
|
|
||||||
index c5cd3057aca1baf6..446fed18365cfd13 100644
|
|
||||||
--- a/sysdeps/sparc/sparc64/dl-irel.h
|
|
||||||
+++ b/sysdeps/sparc/sparc64/dl-irel.h
|
|
||||||
@@ -59,7 +59,7 @@ elf_irela (const Elf64_Rela *reloc)
|
|
||||||
else if (r_type == R_SPARC_NONE)
|
|
||||||
;
|
|
||||||
else
|
|
||||||
- __libc_fatal ("unexpected reloc type in static binary");
|
|
||||||
+ __libc_fatal ("Unexpected reloc type in static binary.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* dl-irel.h */
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/netlink_assert_response.c b/sysdeps/unix/sysv/linux/netlink_assert_response.c
|
|
||||||
index f31ccb52ffa56436..6afc3a17ced18e1c 100644
|
|
||||||
--- a/sysdeps/unix/sysv/linux/netlink_assert_response.c
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/netlink_assert_response.c
|
|
||||||
@@ -72,12 +72,12 @@ __netlink_assert_response (int fd, ssize_t result)
|
|
||||||
char message[200];
|
|
||||||
if (family < 0)
|
|
||||||
__snprintf (message, sizeof (message),
|
|
||||||
- "Unexpected error %d on netlink descriptor %d",
|
|
||||||
+ "Unexpected error %d on netlink descriptor %d.\n",
|
|
||||||
error_code, fd);
|
|
||||||
else
|
|
||||||
__snprintf (message, sizeof (message),
|
|
||||||
"Unexpected error %d on netlink descriptor %d"
|
|
||||||
- " (address family %d)",
|
|
||||||
+ " (address family %d).\n",
|
|
||||||
error_code, fd, family);
|
|
||||||
__libc_fatal (message);
|
|
||||||
}
|
|
||||||
diff --git a/sysdeps/x86_64/dl-irel.h b/sysdeps/x86_64/dl-irel.h
|
|
||||||
index 6ecc50fb42333c19..33f100d8b1781ea7 100644
|
|
||||||
--- a/sysdeps/x86_64/dl-irel.h
|
|
||||||
+++ b/sysdeps/x86_64/dl-irel.h
|
|
||||||
@@ -45,7 +45,7 @@ elf_irela (const ElfW(Rela) *reloc)
|
|
||||||
*reloc_addr = value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
- __libc_fatal ("unexpected reloc type in static binary");
|
|
||||||
+ __libc_fatal ("Unexpected reloc type in static binary.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* dl-irel.h */
|
|
@ -1,24 +0,0 @@
|
|||||||
commit e4e4fde51a309801af5eed72d3494cbf4b7737aa
|
|
||||||
Author: Paul Eggert <eggert@cs.ucla.edu>
|
|
||||||
Date: Tue Sep 18 15:02:10 2018 -0700
|
|
||||||
|
|
||||||
Fix tzfile low-memory assertion failure
|
|
||||||
|
|
||||||
[BZ #21716]
|
|
||||||
* time/tzfile.c (__tzfile_read): Check for memory exhaustion
|
|
||||||
when registering time zone abbreviations.
|
|
||||||
|
|
||||||
diff --git a/time/tzfile.c b/time/tzfile.c
|
|
||||||
index 2a385b92bcdefec0..ea6e94030392fc75 100644
|
|
||||||
--- a/time/tzfile.c
|
|
||||||
+++ b/time/tzfile.c
|
|
||||||
@@ -410,7 +410,8 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
|
|
||||||
|
|
||||||
/* First "register" all timezone names. */
|
|
||||||
for (i = 0; i < num_types; ++i)
|
|
||||||
- (void) __tzstring (&zone_names[types[i].idx]);
|
|
||||||
+ if (__tzstring (&zone_names[types[i].idx]) == NULL)
|
|
||||||
+ goto ret_free_transitions;
|
|
||||||
|
|
||||||
/* Find the standard and daylight time offsets used by the rule file.
|
|
||||||
We choose the offsets in the types of each flavor that are
|
|
@ -1,70 +0,0 @@
|
|||||||
commit 35e3fbc4512c880fccb35b8e3abd132d4be18480
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Mon Nov 19 15:35:03 2018 +0100
|
|
||||||
|
|
||||||
support: Print timestamps in timeout handler
|
|
||||||
|
|
||||||
This is sometimes useful to determine if a test truly got stuck, or if
|
|
||||||
it was making progress (logging information to standard output) and
|
|
||||||
was merely slow to finish.
|
|
||||||
|
|
||||||
diff --git a/support/support_test_main.c b/support/support_test_main.c
|
|
||||||
index 23429779aca85613..fa3c2e06dee5ae0f 100644
|
|
||||||
--- a/support/support_test_main.c
|
|
||||||
+++ b/support/support_test_main.c
|
|
||||||
@@ -30,6 +30,7 @@
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/resource.h>
|
|
||||||
+#include <sys/time.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <time.h>
|
|
||||||
@@ -86,6 +87,19 @@ static pid_t test_pid;
|
|
||||||
/* The cleanup handler passed to test_main. */
|
|
||||||
static void (*cleanup_function) (void);
|
|
||||||
|
|
||||||
+static void
|
|
||||||
+print_timestamp (const char *what, struct timeval tv)
|
|
||||||
+{
|
|
||||||
+ struct tm tm;
|
|
||||||
+ if (gmtime_r (&tv.tv_sec, &tm) == NULL)
|
|
||||||
+ printf ("%s: %lld.%06d\n",
|
|
||||||
+ what, (long long int) tv.tv_sec, (int) tv.tv_usec);
|
|
||||||
+ else
|
|
||||||
+ printf ("%s: %04d-%02d-%02dT%02d:%02d:%02d.%06d\n",
|
|
||||||
+ what, 1900 + tm.tm_year, tm.tm_mon + 1, tm.tm_mday,
|
|
||||||
+ tm.tm_hour, tm.tm_min, tm.tm_sec, (int) tv.tv_usec);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/* Timeout handler. We kill the child and exit with an error. */
|
|
||||||
static void
|
|
||||||
__attribute__ ((noreturn))
|
|
||||||
@@ -94,6 +108,13 @@ signal_handler (int sig)
|
|
||||||
int killed;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
+ /* Do this first to avoid further interference from the
|
|
||||||
+ subprocess. */
|
|
||||||
+ struct timeval now;
|
|
||||||
+ bool now_available = gettimeofday (&now, NULL) == 0;
|
|
||||||
+ struct stat64 st;
|
|
||||||
+ bool st_available = fstat64 (STDOUT_FILENO, &st) == 0 && st.st_mtime != 0;
|
|
||||||
+
|
|
||||||
assert (test_pid > 1);
|
|
||||||
/* Kill the whole process group. */
|
|
||||||
kill (-test_pid, SIGKILL);
|
|
||||||
@@ -144,6 +165,13 @@ signal_handler (int sig)
|
|
||||||
printf ("Timed out: killed the child process but it exited %d\n",
|
|
||||||
WEXITSTATUS (status));
|
|
||||||
|
|
||||||
+ if (now_available)
|
|
||||||
+ print_timestamp ("Termination time", now);
|
|
||||||
+ if (st_available)
|
|
||||||
+ print_timestamp ("Last write to standard output",
|
|
||||||
+ (struct timeval) { st.st_mtim.tv_sec,
|
|
||||||
+ st.st_mtim.tv_nsec / 1000 });
|
|
||||||
+
|
|
||||||
/* Exit with an error. */
|
|
||||||
exit (1);
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
commit d6db68e66dff25d12c3bc5641b60cbd7fb6ab44f
|
|
||||||
Author: Moritz Eckert <m.eckert@cs.ucsb.edu>
|
|
||||||
Date: Thu Aug 16 21:08:36 2018 -0400
|
|
||||||
|
|
||||||
malloc: Mitigate null-byte overflow attacks
|
|
||||||
|
|
||||||
* malloc/malloc.c (_int_free): Check for corrupt prev_size vs size.
|
|
||||||
(malloc_consolidate): Likewise.
|
|
||||||
|
|
||||||
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
|
||||||
index 13c52f376859562d..e450597e2e527fb7 100644
|
|
||||||
--- a/malloc/malloc.c
|
|
||||||
+++ b/malloc/malloc.c
|
|
||||||
@@ -4306,6 +4306,8 @@ _int_free (mstate av, mchunkptr p, int have_lock)
|
|
||||||
prevsize = prev_size (p);
|
|
||||||
size += prevsize;
|
|
||||||
p = chunk_at_offset(p, -((long) prevsize));
|
|
||||||
+ if (__glibc_unlikely (chunksize(p) != prevsize))
|
|
||||||
+ malloc_printerr ("corrupted size vs. prev_size while consolidating");
|
|
||||||
unlink(av, p, bck, fwd);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -4467,6 +4469,8 @@ static void malloc_consolidate(mstate av)
|
|
||||||
prevsize = prev_size (p);
|
|
||||||
size += prevsize;
|
|
||||||
p = chunk_at_offset(p, -((long) prevsize));
|
|
||||||
+ if (__glibc_unlikely (chunksize(p) != prevsize))
|
|
||||||
+ malloc_printerr ("corrupted size vs. prev_size in fastbins");
|
|
||||||
unlink(av, p, bck, fwd);
|
|
||||||
}
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
|||||||
commit 30a17d8c95fbfb15c52d1115803b63aaa73a285c
|
|
||||||
Author: Pochang Chen <johnchen902@gmail.com>
|
|
||||||
Date: Thu Aug 16 15:24:24 2018 -0400
|
|
||||||
|
|
||||||
malloc: Verify size of top chunk.
|
|
||||||
|
|
||||||
The House of Force is a well-known technique to exploit heap
|
|
||||||
overflow. In essence, this exploit takes three steps:
|
|
||||||
1. Overwrite the size of top chunk with very large value (e.g. -1).
|
|
||||||
2. Request x bytes from top chunk. As the size of top chunk
|
|
||||||
is corrupted, x can be arbitrarily large and top chunk will
|
|
||||||
still be offset by x.
|
|
||||||
3. The next allocation from top chunk will thus be controllable.
|
|
||||||
|
|
||||||
If we verify the size of top chunk at step 2, we can stop such attack.
|
|
||||||
|
|
||||||
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
|
||||||
index e450597e2e527fb7..d8d4581a9dcea80a 100644
|
|
||||||
--- a/malloc/malloc.c
|
|
||||||
+++ b/malloc/malloc.c
|
|
||||||
@@ -4084,6 +4084,9 @@ _int_malloc (mstate av, size_t bytes)
|
|
||||||
victim = av->top;
|
|
||||||
size = chunksize (victim);
|
|
||||||
|
|
||||||
+ if (__glibc_unlikely (size > av->system_mem))
|
|
||||||
+ malloc_printerr ("malloc(): corrupted top size");
|
|
||||||
+
|
|
||||||
if ((unsigned long) (size) >= (unsigned long) (nb + MINSIZE))
|
|
||||||
{
|
|
||||||
remainder_size = size - nb;
|
|
@ -1,122 +0,0 @@
|
|||||||
commit b90ddd08f6dd688e651df9ee89ca3a69ff88cd0c
|
|
||||||
Author: Istvan Kurucsai <pistukem@gmail.com>
|
|
||||||
Date: Tue Jan 16 14:54:32 2018 +0100
|
|
||||||
|
|
||||||
malloc: Additional checks for unsorted bin integrity I.
|
|
||||||
|
|
||||||
On Thu, Jan 11, 2018 at 3:50 PM, Florian Weimer <fweimer@redhat.com> wrote:
|
|
||||||
> On 11/07/2017 04:27 PM, Istvan Kurucsai wrote:
|
|
||||||
>>
|
|
||||||
>> + next = chunk_at_offset (victim, size);
|
|
||||||
>
|
|
||||||
>
|
|
||||||
> For new code, we prefer declarations with initializers.
|
|
||||||
|
|
||||||
Noted.
|
|
||||||
|
|
||||||
>> + if (__glibc_unlikely (chunksize_nomask (victim) <= 2 * SIZE_SZ)
|
|
||||||
>> + || __glibc_unlikely (chunksize_nomask (victim) >
|
|
||||||
>> av->system_mem))
|
|
||||||
>> + malloc_printerr("malloc(): invalid size (unsorted)");
|
|
||||||
>> + if (__glibc_unlikely (chunksize_nomask (next) < 2 * SIZE_SZ)
|
|
||||||
>> + || __glibc_unlikely (chunksize_nomask (next) >
|
|
||||||
>> av->system_mem))
|
|
||||||
>> + malloc_printerr("malloc(): invalid next size (unsorted)");
|
|
||||||
>> + if (__glibc_unlikely ((prev_size (next) & ~(SIZE_BITS)) !=
|
|
||||||
>> size))
|
|
||||||
>> + malloc_printerr("malloc(): mismatching next->prev_size
|
|
||||||
>> (unsorted)");
|
|
||||||
>
|
|
||||||
>
|
|
||||||
> I think this check is redundant because prev_size (next) and chunksize
|
|
||||||
> (victim) are loaded from the same memory location.
|
|
||||||
|
|
||||||
I'm fairly certain that it compares mchunk_size of victim against
|
|
||||||
mchunk_prev_size of the next chunk, i.e. the size of victim in its
|
|
||||||
header and footer.
|
|
||||||
|
|
||||||
>> + if (__glibc_unlikely (bck->fd != victim)
|
|
||||||
>> + || __glibc_unlikely (victim->fd != unsorted_chunks (av)))
|
|
||||||
>> + malloc_printerr("malloc(): unsorted double linked list
|
|
||||||
>> corrupted");
|
|
||||||
>> + if (__glibc_unlikely (prev_inuse(next)))
|
|
||||||
>> + malloc_printerr("malloc(): invalid next->prev_inuse
|
|
||||||
>> (unsorted)");
|
|
||||||
>
|
|
||||||
>
|
|
||||||
> There's a missing space after malloc_printerr.
|
|
||||||
|
|
||||||
Noted.
|
|
||||||
|
|
||||||
> Why do you keep using chunksize_nomask? We never investigated why the
|
|
||||||
> original code uses it. It may have been an accident.
|
|
||||||
|
|
||||||
You are right, I don't think it makes a difference in these checks. So
|
|
||||||
the size local can be reused for the checks against victim. For next,
|
|
||||||
leaving it as such avoids the masking operation.
|
|
||||||
|
|
||||||
> Again, for non-main arenas, the checks against av->system_mem could be made
|
|
||||||
> tighter (against the heap size). Maybe you could put the condition into a
|
|
||||||
> separate inline function?
|
|
||||||
|
|
||||||
We could also do a chunk boundary check similar to what I proposed in
|
|
||||||
the thread for the first patch in the series to be even more strict.
|
|
||||||
I'll gladly try to implement either but believe that refining these
|
|
||||||
checks would bring less benefits than in the case of the top chunk.
|
|
||||||
Intra-arena or intra-heap overlaps would still be doable here with
|
|
||||||
unsorted chunks and I don't see any way to counter that besides more
|
|
||||||
generic measures like randomizing allocations and your metadata
|
|
||||||
encoding patches.
|
|
||||||
|
|
||||||
I've attached a revised version with the above comments incorporated
|
|
||||||
but without the refined checks.
|
|
||||||
|
|
||||||
Thanks,
|
|
||||||
Istvan
|
|
||||||
|
|
||||||
From a12d5d40fd7aed5fa10fc444dcb819947b72b315 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Istvan Kurucsai <pistukem@gmail.com>
|
|
||||||
Date: Tue, 16 Jan 2018 14:48:16 +0100
|
|
||||||
Subject: [PATCH v2 1/1] malloc: Additional checks for unsorted bin integrity
|
|
||||||
I.
|
|
||||||
|
|
||||||
Ensure the following properties of chunks encountered during binning:
|
|
||||||
- victim chunk has reasonable size
|
|
||||||
- next chunk has reasonable size
|
|
||||||
- next->prev_size == victim->size
|
|
||||||
- valid double linked list
|
|
||||||
- PREV_INUSE of next chunk is unset
|
|
||||||
|
|
||||||
* malloc/malloc.c (_int_malloc): Additional binning code checks.
|
|
||||||
|
|
||||||
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
|
||||||
index d8d4581a9dcea80a..dad0e73735789530 100644
|
|
||||||
--- a/malloc/malloc.c
|
|
||||||
+++ b/malloc/malloc.c
|
|
||||||
@@ -3724,11 +3724,22 @@ _int_malloc (mstate av, size_t bytes)
|
|
||||||
while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))
|
|
||||||
{
|
|
||||||
bck = victim->bk;
|
|
||||||
- if (__builtin_expect (chunksize_nomask (victim) <= 2 * SIZE_SZ, 0)
|
|
||||||
- || __builtin_expect (chunksize_nomask (victim)
|
|
||||||
- > av->system_mem, 0))
|
|
||||||
- malloc_printerr ("malloc(): memory corruption");
|
|
||||||
size = chunksize (victim);
|
|
||||||
+ mchunkptr next = chunk_at_offset (victim, size);
|
|
||||||
+
|
|
||||||
+ if (__glibc_unlikely (size <= 2 * SIZE_SZ)
|
|
||||||
+ || __glibc_unlikely (size > av->system_mem))
|
|
||||||
+ malloc_printerr ("malloc(): invalid size (unsorted)");
|
|
||||||
+ if (__glibc_unlikely (chunksize_nomask (next) < 2 * SIZE_SZ)
|
|
||||||
+ || __glibc_unlikely (chunksize_nomask (next) > av->system_mem))
|
|
||||||
+ malloc_printerr ("malloc(): invalid next size (unsorted)");
|
|
||||||
+ if (__glibc_unlikely ((prev_size (next) & ~(SIZE_BITS)) != size))
|
|
||||||
+ malloc_printerr ("malloc(): mismatching next->prev_size (unsorted)");
|
|
||||||
+ if (__glibc_unlikely (bck->fd != victim)
|
|
||||||
+ || __glibc_unlikely (victim->fd != unsorted_chunks (av)))
|
|
||||||
+ malloc_printerr ("malloc(): unsorted double linked list corrupted");
|
|
||||||
+ if (__glibc_unlikely (prev_inuse(next)))
|
|
||||||
+ malloc_printerr ("malloc(): invalid next->prev_inuse (unsorted)");
|
|
||||||
|
|
||||||
/*
|
|
||||||
If a small request, try to use last remainder if it is the
|
|
@ -1,26 +0,0 @@
|
|||||||
The below commit contains only a whitespace change and was backported in
|
|
||||||
order to avoid future conflicts.
|
|
||||||
|
|
||||||
commit 35cfefd96062145eeb8aee6bd72d07e0909a6b2e
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Mon Aug 20 14:57:13 2018 +0200
|
|
||||||
|
|
||||||
malloc: Add ChangeLog for accidentally committed change
|
|
||||||
|
|
||||||
Commit b90ddd08f6dd688e651df9ee89ca3a69ff88cd0c ("malloc: Additional
|
|
||||||
checks for unsorted bin integrity I.") was committed without a
|
|
||||||
whitespace fix, so it is adjusted here as well.
|
|
||||||
|
|
||||||
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
|
||||||
index c07463001a65af90..eb6a8ff33c0c313b 100644
|
|
||||||
--- a/malloc/malloc.c
|
|
||||||
+++ b/malloc/malloc.c
|
|
||||||
@@ -3745,7 +3745,7 @@ _int_malloc (mstate av, size_t bytes)
|
|
||||||
if (__glibc_unlikely (bck->fd != victim)
|
|
||||||
|| __glibc_unlikely (victim->fd != unsorted_chunks (av)))
|
|
||||||
malloc_printerr ("malloc(): unsorted double linked list corrupted");
|
|
||||||
- if (__glibc_unlikely (prev_inuse(next)))
|
|
||||||
+ if (__glibc_unlikely (prev_inuse (next)))
|
|
||||||
malloc_printerr ("malloc(): invalid next->prev_inuse (unsorted)");
|
|
||||||
|
|
||||||
/*
|
|
@ -1,38 +0,0 @@
|
|||||||
commit ebe544bf6e8eec35e754fd49efb027c6f161b6cb
|
|
||||||
Author: Istvan Kurucsai <pistukem@gmail.com>
|
|
||||||
Date: Thu Dec 20 23:30:07 2018 -0500
|
|
||||||
|
|
||||||
malloc: Add more integrity checks to mremap_chunk.
|
|
||||||
|
|
||||||
* malloc/malloc.c (mremap_chunk): Additional checks.
|
|
||||||
|
|
||||||
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
|
||||||
index eb6a8ff33c0c313b..4df5cb4862a7b854 100644
|
|
||||||
--- a/malloc/malloc.c
|
|
||||||
+++ b/malloc/malloc.c
|
|
||||||
@@ -2856,16 +2856,22 @@ mremap_chunk (mchunkptr p, size_t new_size)
|
|
||||||
char *cp;
|
|
||||||
|
|
||||||
assert (chunk_is_mmapped (p));
|
|
||||||
- assert (((size + offset) & (GLRO (dl_pagesize) - 1)) == 0);
|
|
||||||
+
|
|
||||||
+ uintptr_t block = (uintptr_t) p - offset;
|
|
||||||
+ uintptr_t mem = (uintptr_t) chunk2mem(p);
|
|
||||||
+ size_t total_size = offset + size;
|
|
||||||
+ if (__glibc_unlikely ((block | total_size) & (pagesize - 1)) != 0
|
|
||||||
+ || __glibc_unlikely (!powerof2 (mem & (pagesize - 1))))
|
|
||||||
+ malloc_printerr("mremap_chunk(): invalid pointer");
|
|
||||||
|
|
||||||
/* Note the extra SIZE_SZ overhead as in mmap_chunk(). */
|
|
||||||
new_size = ALIGN_UP (new_size + offset + SIZE_SZ, pagesize);
|
|
||||||
|
|
||||||
/* No need to remap if the number of pages does not change. */
|
|
||||||
- if (size + offset == new_size)
|
|
||||||
+ if (total_size == new_size)
|
|
||||||
return p;
|
|
||||||
|
|
||||||
- cp = (char *) __mremap ((char *) p - offset, size + offset, new_size,
|
|
||||||
+ cp = (char *) __mremap ((char *) block, total_size, new_size,
|
|
||||||
MREMAP_MAYMOVE);
|
|
||||||
|
|
||||||
if (cp == MAP_FAILED)
|
|
@ -1,38 +0,0 @@
|
|||||||
commit c0e82f117357a941e4d40fcc08babbd6a3c3a1b5
|
|
||||||
Author: Istvan Kurucsai <pistukem@gmail.com>
|
|
||||||
Date: Fri Dec 21 00:13:01 2018 -0500
|
|
||||||
|
|
||||||
malloc: Check the alignment of mmapped chunks before unmapping.
|
|
||||||
|
|
||||||
* malloc/malloc.c (munmap_chunk): Verify chunk alignment.
|
|
||||||
|
|
||||||
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
|
||||||
index 4df5cb4862a7b854..4412a4ffc83b013b 100644
|
|
||||||
--- a/malloc/malloc.c
|
|
||||||
+++ b/malloc/malloc.c
|
|
||||||
@@ -2817,6 +2817,7 @@ systrim (size_t pad, mstate av)
|
|
||||||
static void
|
|
||||||
munmap_chunk (mchunkptr p)
|
|
||||||
{
|
|
||||||
+ size_t pagesize = GLRO (dl_pagesize);
|
|
||||||
INTERNAL_SIZE_T size = chunksize (p);
|
|
||||||
|
|
||||||
assert (chunk_is_mmapped (p));
|
|
||||||
@@ -2826,6 +2827,7 @@ munmap_chunk (mchunkptr p)
|
|
||||||
if (DUMPED_MAIN_ARENA_CHUNK (p))
|
|
||||||
return;
|
|
||||||
|
|
||||||
+ uintptr_t mem = (uintptr_t) chunk2mem (p);
|
|
||||||
uintptr_t block = (uintptr_t) p - prev_size (p);
|
|
||||||
size_t total_size = prev_size (p) + size;
|
|
||||||
/* Unfortunately we have to do the compilers job by hand here. Normally
|
|
||||||
@@ -2833,7 +2835,8 @@ munmap_chunk (mchunkptr p)
|
|
||||||
page size. But gcc does not recognize the optimization possibility
|
|
||||||
(in the moment at least) so we combine the two values into one before
|
|
||||||
the bit test. */
|
|
||||||
- if (__builtin_expect (((block | total_size) & (GLRO (dl_pagesize) - 1)) != 0, 0))
|
|
||||||
+ if (__glibc_unlikely ((block | total_size) & (pagesize - 1)) != 0
|
|
||||||
+ || __glibc_unlikely (!powerof2 (mem & (pagesize - 1))))
|
|
||||||
malloc_printerr ("munmap_chunk(): invalid pointer");
|
|
||||||
|
|
||||||
atomic_decrement (&mp_.n_mmaps);
|
|
@ -1,31 +0,0 @@
|
|||||||
commit 5b06f538c5aee0389ed034f60d90a8884d6d54de
|
|
||||||
Author: Adam Maris <amaris@redhat.com>
|
|
||||||
Date: Thu Mar 14 16:51:16 2019 -0400
|
|
||||||
|
|
||||||
malloc: Check for large bin list corruption when inserting unsorted chunk
|
|
||||||
|
|
||||||
Fixes bug 24216. This patch adds security checks for bk and bk_nextsize pointers
|
|
||||||
of chunks in large bin when inserting chunk from unsorted bin. It was possible
|
|
||||||
to write the pointer to victim (newly inserted chunk) to arbitrary memory
|
|
||||||
locations if bk or bk_nextsize pointers of the next large bin chunk
|
|
||||||
got corrupted.
|
|
||||||
|
|
||||||
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
|
||||||
index 4412a4ffc83b013b..723d393f529bdb4c 100644
|
|
||||||
--- a/malloc/malloc.c
|
|
||||||
+++ b/malloc/malloc.c
|
|
||||||
@@ -3876,10 +3876,14 @@ _int_malloc (mstate av, size_t bytes)
|
|
||||||
{
|
|
||||||
victim->fd_nextsize = fwd;
|
|
||||||
victim->bk_nextsize = fwd->bk_nextsize;
|
|
||||||
+ if (__glibc_unlikely (fwd->bk_nextsize->fd_nextsize != fwd))
|
|
||||||
+ malloc_printerr ("malloc(): largebin double linked list corrupted (nextsize)");
|
|
||||||
fwd->bk_nextsize = victim;
|
|
||||||
victim->bk_nextsize->fd_nextsize = victim;
|
|
||||||
}
|
|
||||||
bck = fwd->bk;
|
|
||||||
+ if (bck->fd != fwd)
|
|
||||||
+ malloc_printerr ("malloc(): largebin double linked list corrupted (bk)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
@ -1,307 +0,0 @@
|
|||||||
commit f0458cf4f9ff3d870c43b624e6dccaaf657d5e83
|
|
||||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
|
||||||
Date: Mon Aug 27 09:42:50 2018 -0300
|
|
||||||
|
|
||||||
powerpc: Only enable TLE with PPC_FEATURE2_HTM_NOSC
|
|
||||||
|
|
||||||
Linux from 3.9 through 4.2 does not abort HTM transaction on syscalls,
|
|
||||||
instead it suspend and resume it when leaving the kernel. The
|
|
||||||
side-effects of the syscall will always remain visible, even if the
|
|
||||||
transaction is aborted. This is an issue when transaction is used along
|
|
||||||
with futex syscall, on pthread_cond_wait for instance, where the futex
|
|
||||||
call might succeed but the transaction is rolled back leading the
|
|
||||||
pthread_cond object in an inconsistent state.
|
|
||||||
|
|
||||||
Glibc used to prevent it by always aborting a transaction before issuing
|
|
||||||
a syscall. Linux 4.2 also decided to abort active transaction in
|
|
||||||
syscalls which makes the glibc workaround superfluous. Worse, glibc
|
|
||||||
transaction abortion leads to a performance issue on recent kernels
|
|
||||||
where the HTM state is saved/restore lazily (v4.9). By aborting a
|
|
||||||
transaction on every syscalls, regardless whether a transaction has being
|
|
||||||
initiated before, GLIBS makes the kernel always save/restore HTM state
|
|
||||||
(it can not even lazily disable it after a certain number of syscall
|
|
||||||
iterations).
|
|
||||||
|
|
||||||
Because of this shortcoming, Transactional Lock Elision is just enabled
|
|
||||||
when it has been explicitly set (either by tunables of by a configure
|
|
||||||
switch) and if kernel aborts HTM transactions on syscalls
|
|
||||||
(PPC_FEATURE2_HTM_NOSC). It is reported that using simple benchmark [1],
|
|
||||||
the context-switch is about 5% faster by not issuing a tabort in every
|
|
||||||
syscall in newer kernels.
|
|
||||||
|
|
||||||
Checked on powerpc64le-linux-gnu with 4.4.0 kernel (Ubuntu 16.04).
|
|
||||||
|
|
||||||
* NEWS: Add note about new TLE support on powerpc64le.
|
|
||||||
* sysdeps/powerpc/nptl/tcb-offsets.sym (TM_CAPABLE): Remove.
|
|
||||||
* sysdeps/powerpc/nptl/tls.h (tcbhead_t): Rename tm_capable to
|
|
||||||
__ununsed1.
|
|
||||||
(TLS_INIT_TP, TLS_DEFINE_INIT_TP): Remove tm_capable setup.
|
|
||||||
(THREAD_GET_TM_CAPABLE, THREAD_SET_TM_CAPABLE): Remove macros.
|
|
||||||
* sysdeps/powerpc/powerpc32/sysdep.h,
|
|
||||||
sysdeps/powerpc/powerpc64/sysdep.h (ABORT_TRANSACTION_IMPL,
|
|
||||||
ABORT_TRANSACTION): Remove macros.
|
|
||||||
* sysdeps/powerpc/sysdep.h (ABORT_TRANSACTION): Likewise.
|
|
||||||
* sysdeps/unix/sysv/linux/powerpc/elision-conf.c (elision_init): Set
|
|
||||||
__pthread_force_elision iff PPC_FEATURE2_HTM_NOSC is set.
|
|
||||||
* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h,
|
|
||||||
sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
|
|
||||||
sysdeps/unix/sysv/linux/powerpc/syscall.S (ABORT_TRANSACTION): Remove
|
|
||||||
usage.
|
|
||||||
* sysdeps/unix/sysv/linux/powerpc/not-errno.h: Remove file.
|
|
||||||
|
|
||||||
Reported-by: Breno Leitão <leitao@debian.org>
|
|
||||||
|
|
||||||
diff --git a/sysdeps/powerpc/nptl/tcb-offsets.sym b/sysdeps/powerpc/nptl/tcb-offsets.sym
|
|
||||||
index e5bb2b3..4c01615 100644
|
|
||||||
--- a/sysdeps/powerpc/nptl/tcb-offsets.sym
|
|
||||||
+++ b/sysdeps/powerpc/nptl/tcb-offsets.sym
|
|
||||||
@@ -21,7 +21,6 @@ DSO_SLOT2 (offsetof (tcbhead_t, dso_slot2) - TLS_TCB_OFFSET - sizeof (tcbhead_
|
|
||||||
#ifdef __powerpc64__
|
|
||||||
TCB_AT_PLATFORM (offsetof (tcbhead_t, at_platform) - TLS_TCB_OFFSET - sizeof(tcbhead_t))
|
|
||||||
#endif
|
|
||||||
-TM_CAPABLE (offsetof (tcbhead_t, tm_capable) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
|
|
||||||
#ifndef __powerpc64__
|
|
||||||
TCB_AT_PLATFORM (offsetof (tcbhead_t, at_platform) - TLS_TCB_OFFSET - sizeof(tcbhead_t))
|
|
||||||
PADDING (offsetof (tcbhead_t, padding) - TLS_TCB_OFFSET - sizeof(tcbhead_t))
|
|
||||||
diff --git a/sysdeps/powerpc/nptl/tls.h b/sysdeps/powerpc/nptl/tls.h
|
|
||||||
index f88fed5..8317ca7 100644
|
|
||||||
--- a/sysdeps/powerpc/nptl/tls.h
|
|
||||||
+++ b/sysdeps/powerpc/nptl/tls.h
|
|
||||||
@@ -67,8 +67,7 @@ typedef struct
|
|
||||||
uint32_t padding;
|
|
||||||
uint32_t at_platform;
|
|
||||||
#endif
|
|
||||||
- /* Indicate if HTM capable (ISA 2.07). */
|
|
||||||
- uint32_t tm_capable;
|
|
||||||
+ uint32_t __unused;
|
|
||||||
/* Reservation for AT_PLATFORM data - powerpc64. */
|
|
||||||
#ifdef __powerpc64__
|
|
||||||
uint32_t at_platform;
|
|
||||||
@@ -142,7 +141,6 @@ register void *__thread_register __asm__ ("r13");
|
|
||||||
# define TLS_INIT_TP(tcbp) \
|
|
||||||
({ \
|
|
||||||
__thread_register = (void *) (tcbp) + TLS_TCB_OFFSET; \
|
|
||||||
- THREAD_SET_TM_CAPABLE (__tcb_hwcap & PPC_FEATURE2_HAS_HTM ? 1 : 0); \
|
|
||||||
THREAD_SET_HWCAP (__tcb_hwcap); \
|
|
||||||
THREAD_SET_AT_PLATFORM (__tcb_platform); \
|
|
||||||
NULL; \
|
|
||||||
@@ -151,8 +149,6 @@ register void *__thread_register __asm__ ("r13");
|
|
||||||
/* Value passed to 'clone' for initialization of the thread register. */
|
|
||||||
# define TLS_DEFINE_INIT_TP(tp, pd) \
|
|
||||||
void *tp = (void *) (pd) + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE; \
|
|
||||||
- (((tcbhead_t *) ((char *) tp - TLS_TCB_OFFSET))[-1].tm_capable) = \
|
|
||||||
- THREAD_GET_TM_CAPABLE (); \
|
|
||||||
(((tcbhead_t *) ((char *) tp - TLS_TCB_OFFSET))[-1].hwcap) = \
|
|
||||||
THREAD_GET_HWCAP (); \
|
|
||||||
(((tcbhead_t *) ((char *) tp - TLS_TCB_OFFSET))[-1].at_platform) = \
|
|
||||||
@@ -210,13 +206,6 @@ register void *__thread_register __asm__ ("r13");
|
|
||||||
+ TLS_PRE_TCB_SIZE))[-1].pointer_guard \
|
|
||||||
= THREAD_GET_POINTER_GUARD())
|
|
||||||
|
|
||||||
-/* tm_capable field in TCB head. */
|
|
||||||
-# define THREAD_GET_TM_CAPABLE() \
|
|
||||||
- (((tcbhead_t *) ((char *) __thread_register \
|
|
||||||
- - TLS_TCB_OFFSET))[-1].tm_capable)
|
|
||||||
-# define THREAD_SET_TM_CAPABLE(value) \
|
|
||||||
- (THREAD_GET_TM_CAPABLE () = (value))
|
|
||||||
-
|
|
||||||
/* hwcap field in TCB head. */
|
|
||||||
# define THREAD_GET_HWCAP() \
|
|
||||||
(((tcbhead_t *) ((char *) __thread_register \
|
|
||||||
diff --git a/sysdeps/powerpc/powerpc32/sysdep.h b/sysdeps/powerpc/powerpc32/sysdep.h
|
|
||||||
index 5f1294e..93097c5 100644
|
|
||||||
--- a/sysdeps/powerpc/powerpc32/sysdep.h
|
|
||||||
+++ b/sysdeps/powerpc/powerpc32/sysdep.h
|
|
||||||
@@ -90,24 +90,7 @@ GOT_LABEL: ; \
|
|
||||||
cfi_endproc; \
|
|
||||||
ASM_SIZE_DIRECTIVE(name)
|
|
||||||
|
|
||||||
-#if !IS_IN(rtld) && !defined(__SPE__)
|
|
||||||
-# define ABORT_TRANSACTION_IMPL \
|
|
||||||
- cmpwi 2,0; \
|
|
||||||
- beq 1f; \
|
|
||||||
- lwz 0,TM_CAPABLE(2); \
|
|
||||||
- cmpwi 0,0; \
|
|
||||||
- beq 1f; \
|
|
||||||
- li 11,_ABORT_SYSCALL; \
|
|
||||||
- tabort. 11; \
|
|
||||||
- .align 4; \
|
|
||||||
-1:
|
|
||||||
-#else
|
|
||||||
-# define ABORT_TRANSACTION_IMPL
|
|
||||||
-#endif
|
|
||||||
-#define ABORT_TRANSACTION ABORT_TRANSACTION_IMPL
|
|
||||||
-
|
|
||||||
#define DO_CALL(syscall) \
|
|
||||||
- ABORT_TRANSACTION \
|
|
||||||
li 0,syscall; \
|
|
||||||
sc
|
|
||||||
|
|
||||||
diff --git a/sysdeps/powerpc/powerpc64/sysdep.h b/sysdeps/powerpc/powerpc64/sysdep.h
|
|
||||||
index 2df1d9b..50e64f9 100644
|
|
||||||
--- a/sysdeps/powerpc/powerpc64/sysdep.h
|
|
||||||
+++ b/sysdeps/powerpc/powerpc64/sysdep.h
|
|
||||||
@@ -263,24 +263,7 @@ LT_LABELSUFFIX(name,_name_end): ; \
|
|
||||||
TRACEBACK_MASK(name,mask); \
|
|
||||||
END_2(name)
|
|
||||||
|
|
||||||
-#if !IS_IN(rtld)
|
|
||||||
-# define ABORT_TRANSACTION_IMPL \
|
|
||||||
- cmpdi 13,0; \
|
|
||||||
- beq 1f; \
|
|
||||||
- lwz 0,TM_CAPABLE(13); \
|
|
||||||
- cmpwi 0,0; \
|
|
||||||
- beq 1f; \
|
|
||||||
- li 11,_ABORT_SYSCALL; \
|
|
||||||
- tabort. 11; \
|
|
||||||
- .p2align 4; \
|
|
||||||
-1:
|
|
||||||
-#else
|
|
||||||
-# define ABORT_TRANSACTION_IMPL
|
|
||||||
-#endif
|
|
||||||
-#define ABORT_TRANSACTION ABORT_TRANSACTION_IMPL
|
|
||||||
-
|
|
||||||
#define DO_CALL(syscall) \
|
|
||||||
- ABORT_TRANSACTION \
|
|
||||||
li 0,syscall; \
|
|
||||||
sc
|
|
||||||
|
|
||||||
diff --git a/sysdeps/powerpc/sysdep.h b/sysdeps/powerpc/sysdep.h
|
|
||||||
index 8a6d236..c8bf25e 100644
|
|
||||||
--- a/sysdeps/powerpc/sysdep.h
|
|
||||||
+++ b/sysdeps/powerpc/sysdep.h
|
|
||||||
@@ -21,8 +21,6 @@
|
|
||||||
*/
|
|
||||||
#define _SYSDEPS_SYSDEP_H 1
|
|
||||||
#include <bits/hwcap.h>
|
|
||||||
-#include <tls.h>
|
|
||||||
-#include <htm.h>
|
|
||||||
|
|
||||||
#define PPC_FEATURE_970 (PPC_FEATURE_POWER4 + PPC_FEATURE_HAS_ALTIVEC)
|
|
||||||
|
|
||||||
@@ -166,22 +164,4 @@
|
|
||||||
#define ALIGNARG(log2) log2
|
|
||||||
#define ASM_SIZE_DIRECTIVE(name) .size name,.-name
|
|
||||||
|
|
||||||
-#else
|
|
||||||
-
|
|
||||||
-/* Linux kernel powerpc documentation [1] states issuing a syscall inside a
|
|
||||||
- transaction is not recommended and may lead to undefined behavior. It
|
|
||||||
- also states syscalls do not abort transactions. To avoid such traps,
|
|
||||||
- we abort transaction just before syscalls.
|
|
||||||
-
|
|
||||||
- [1] Documentation/powerpc/transactional_memory.txt [Syscalls] */
|
|
||||||
-#if !IS_IN(rtld) && !defined(__SPE__)
|
|
||||||
-# define ABORT_TRANSACTION \
|
|
||||||
- ({ \
|
|
||||||
- if (THREAD_GET_TM_CAPABLE ()) \
|
|
||||||
- __libc_tabort (_ABORT_SYSCALL); \
|
|
||||||
- })
|
|
||||||
-#else
|
|
||||||
-# define ABORT_TRANSACTION
|
|
||||||
-#endif
|
|
||||||
-
|
|
||||||
#endif /* __ASSEMBLER__ */
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/elision-conf.c b/sysdeps/unix/sysv/linux/powerpc/elision-conf.c
|
|
||||||
index 906882a..fc82bd1 100644
|
|
||||||
--- a/sysdeps/unix/sysv/linux/powerpc/elision-conf.c
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/powerpc/elision-conf.c
|
|
||||||
@@ -127,6 +127,26 @@ elision_init (int argc __attribute__ ((unused)),
|
|
||||||
TUNABLE_CALLBACK (set_elision_skip_trylock_internal_abort));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+ /* Linux from 3.9 through 4.2 do not abort HTM transaction on syscalls,
|
|
||||||
+ instead it suspends the transaction and resumes it when returning to
|
|
||||||
+ usercode. The side-effects of the syscall will always remain visible,
|
|
||||||
+ even if the transaction is aborted. This is an issue when a transaction
|
|
||||||
+ is used along with futex syscall, on pthread_cond_wait for instance,
|
|
||||||
+ where futex might succeed but the transaction is rolled back leading
|
|
||||||
+ the condition variable object in an inconsistent state.
|
|
||||||
+
|
|
||||||
+ Glibc used to prevent it by always aborting a transaction before issuing
|
|
||||||
+ a syscall. Linux 4.2 also decided to abort active transaction in
|
|
||||||
+ syscalls which makes the glibc workaround superflours. Worse, glibc
|
|
||||||
+ transaction abortions leads to a performance issues on recent kernels.
|
|
||||||
+
|
|
||||||
+ So Lock Elision is just enabled when it has been explict set (either
|
|
||||||
+ by tunables of by a configure switch) and if kernel aborts HTM
|
|
||||||
+ transactions on syscalls (PPC_FEATURE2_HTM_NOSC) */
|
|
||||||
+
|
|
||||||
+ __pthread_force_elision = (__pthread_force_elision
|
|
||||||
+ && GLRO (dl_hwcap2) & PPC_FEATURE2_HTM_NOSC);
|
|
||||||
+
|
|
||||||
if (!__pthread_force_elision)
|
|
||||||
__elision_aconf.try_tbegin = 0; /* Disable elision on rwlocks. */
|
|
||||||
}
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/not-errno.h b/sysdeps/unix/sysv/linux/powerpc/not-errno.h
|
|
||||||
deleted file mode 100644
|
|
||||||
index 27da21b..0000000
|
|
||||||
--- a/sysdeps/unix/sysv/linux/powerpc/not-errno.h
|
|
||||||
+++ /dev/null
|
|
||||||
@@ -1,30 +0,0 @@
|
|
||||||
-/* Syscall wrapper that do not set errno. Linux powerpc version.
|
|
||||||
- Copyright (C) 2018 Free Software Foundation, Inc.
|
|
||||||
- This file is part of the GNU C Library.
|
|
||||||
-
|
|
||||||
- The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
- modify it under the terms of the GNU Lesser General Public
|
|
||||||
- License as published by the Free Software Foundation; either
|
|
||||||
- version 2.1 of the License, or (at your option) any later version.
|
|
||||||
-
|
|
||||||
- The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
- Lesser General Public License for more details.
|
|
||||||
-
|
|
||||||
- You should have received a copy of the GNU Lesser General Public
|
|
||||||
- License along with the GNU C Library; if not, see
|
|
||||||
- <http://www.gnu.org/licenses/>. */
|
|
||||||
-
|
|
||||||
-/* __access_noerrno is used during process initialization in elf/dl-tunables.c
|
|
||||||
- before the TCB is initialized, prohibiting the usage of
|
|
||||||
- ABORT_TRANSACTION. */
|
|
||||||
-#undef ABORT_TRANSACTION
|
|
||||||
-#define ABORT_TRANSACTION
|
|
||||||
-
|
|
||||||
-#include "sysdeps/unix/sysv/linux/not-errno.h"
|
|
||||||
-
|
|
||||||
-/* Recover ABORT_TRANSACTION's previous value, in order to not affect
|
|
||||||
- other syscalls. */
|
|
||||||
-#undef ABORT_TRANSACTION
|
|
||||||
-#define ABORT_TRANSACTION ABORT_TRANSACTION_IMPL
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
|
|
||||||
index f7277d5..ec5c525 100644
|
|
||||||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
|
|
||||||
@@ -109,7 +109,6 @@
|
|
||||||
register long int r11 __asm__ ("r11"); \
|
|
||||||
register long int r12 __asm__ ("r12"); \
|
|
||||||
LOADARGS_##nr(name, args); \
|
|
||||||
- ABORT_TRANSACTION; \
|
|
||||||
__asm__ __volatile__ \
|
|
||||||
("sc \n\t" \
|
|
||||||
"mfcr %0" \
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
|
|
||||||
index 0956cf0..1f17f7b 100644
|
|
||||||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
|
|
||||||
@@ -131,7 +131,6 @@
|
|
||||||
register long int r7 __asm__ ("r7"); \
|
|
||||||
register long int r8 __asm__ ("r8"); \
|
|
||||||
LOADARGS_##nr (name, ##args); \
|
|
||||||
- ABORT_TRANSACTION; \
|
|
||||||
__asm__ __volatile__ \
|
|
||||||
("sc\n\t" \
|
|
||||||
"mfcr %0\n\t" \
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/syscall.S b/sysdeps/unix/sysv/linux/powerpc/syscall.S
|
|
||||||
index 2da9172..bbab613 100644
|
|
||||||
--- a/sysdeps/unix/sysv/linux/powerpc/syscall.S
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/powerpc/syscall.S
|
|
||||||
@@ -18,7 +18,6 @@
|
|
||||||
#include <sysdep.h>
|
|
||||||
|
|
||||||
ENTRY (syscall)
|
|
||||||
- ABORT_TRANSACTION
|
|
||||||
mr r0,r3
|
|
||||||
mr r3,r4
|
|
||||||
mr r4,r5
|
|
@ -1,35 +0,0 @@
|
|||||||
commit d527c860f5a3f0ed687bd03f0cb464612dc23408
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Tue Nov 27 16:12:43 2018 +0100
|
|
||||||
|
|
||||||
CVE-2018-19591: if_nametoindex: Fix descriptor for overlong name [BZ #23927]
|
|
||||||
|
|
||||||
diff --git a/sysdeps/unix/sysv/linux/if_index.c b/sysdeps/unix/sysv/linux/if_index.c
|
|
||||||
index e3d08982d9931108..782fc5e1750e9ead 100644
|
|
||||||
--- a/sysdeps/unix/sysv/linux/if_index.c
|
|
||||||
+++ b/sysdeps/unix/sysv/linux/if_index.c
|
|
||||||
@@ -38,11 +38,6 @@ __if_nametoindex (const char *ifname)
|
|
||||||
return 0;
|
|
||||||
#else
|
|
||||||
struct ifreq ifr;
|
|
||||||
- int fd = __opensock ();
|
|
||||||
-
|
|
||||||
- if (fd < 0)
|
|
||||||
- return 0;
|
|
||||||
-
|
|
||||||
if (strlen (ifname) >= IFNAMSIZ)
|
|
||||||
{
|
|
||||||
__set_errno (ENODEV);
|
|
||||||
@@ -50,6 +45,12 @@ __if_nametoindex (const char *ifname)
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
|
|
||||||
+
|
|
||||||
+ int fd = __opensock ();
|
|
||||||
+
|
|
||||||
+ if (fd < 0)
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
if (__ioctl (fd, SIOCGIFINDEX, &ifr) < 0)
|
|
||||||
{
|
|
||||||
int saved_errno = errno;
|
|
@ -1,142 +0,0 @@
|
|||||||
commit c74a91deaa5de416237c02bbb3e41bda76ca4c7b
|
|
||||||
Author: Florian Weimer <fweimer@redhat.com>
|
|
||||||
Date: Tue Nov 27 21:35:56 2018 +0100
|
|
||||||
|
|
||||||
support: Implement support_quote_string
|
|
||||||
|
|
||||||
Reviewed-by: Jonathan Nieder <jrnieder@gmail.com>
|
|
||||||
|
|
||||||
diff --git a/support/Makefile b/support/Makefile
|
|
||||||
index 2b663fbbfa334ea2..a2536980d1d5a89b 100644
|
|
||||||
--- a/support/Makefile
|
|
||||||
+++ b/support/Makefile
|
|
||||||
@@ -58,6 +58,7 @@ libsupport-routines = \
|
|
||||||
support_openpty \
|
|
||||||
support_paths \
|
|
||||||
support_quote_blob \
|
|
||||||
+ support_quote_string \
|
|
||||||
support_record_failure \
|
|
||||||
support_run_diff \
|
|
||||||
support_shared_allocate \
|
|
||||||
@@ -196,6 +197,7 @@ tests = \
|
|
||||||
tst-support_capture_subprocess \
|
|
||||||
tst-support_format_dns_packet \
|
|
||||||
tst-support_quote_blob \
|
|
||||||
+ tst-support_quote_string \
|
|
||||||
tst-support_record_failure \
|
|
||||||
tst-test_compare \
|
|
||||||
tst-test_compare_blob \
|
|
||||||
diff --git a/support/support.h b/support/support.h
|
|
||||||
index 9418cd11ef6e684d..835e7173eb566355 100644
|
|
||||||
--- a/support/support.h
|
|
||||||
+++ b/support/support.h
|
|
||||||
@@ -69,6 +69,11 @@ void support_write_file_string (const char *path, const char *contents);
|
|
||||||
the result). */
|
|
||||||
char *support_quote_blob (const void *blob, size_t length);
|
|
||||||
|
|
||||||
+/* Quote the contents of the at STR, in such a way that the result
|
|
||||||
+ string can be included in a C literal (in single/double quotes,
|
|
||||||
+ without putting the quotes into the result). */
|
|
||||||
+char *support_quote_string (const char *str);
|
|
||||||
+
|
|
||||||
/* Returns non-zero if the file descriptor is a regular file on a file
|
|
||||||
system which supports holes (that is, seeking and writing does not
|
|
||||||
allocate storage for the range of zeros). FD must refer to a
|
|
||||||
diff --git a/support/support_quote_string.c b/support/support_quote_string.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000..d324371b133a4d66
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/support/support_quote_string.c
|
|
||||||
@@ -0,0 +1,26 @@
|
|
||||||
+/* Quote a string so that it can be used in C literals.
|
|
||||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <http://www.gnu.org/licenses/>. */
|
|
||||||
+
|
|
||||||
+#include <string.h>
|
|
||||||
+#include <support/support.h>
|
|
||||||
+
|
|
||||||
+char *
|
|
||||||
+support_quote_string (const char *str)
|
|
||||||
+{
|
|
||||||
+ return support_quote_blob (str, strlen (str));
|
|
||||||
+}
|
|
||||||
diff --git a/support/tst-support_quote_string.c b/support/tst-support_quote_string.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000000000..3c004759b76e21d7
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/support/tst-support_quote_string.c
|
|
||||||
@@ -0,0 +1,60 @@
|
|
||||||
+/* Test the support_quote_string function.
|
|
||||||
+ Copyright (C) 2018 Free Software Foundation, Inc.
|
|
||||||
+ This file is part of the GNU C Library.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is free software; you can redistribute it and/or
|
|
||||||
+ modify it under the terms of the GNU Lesser General Public
|
|
||||||
+ License as published by the Free Software Foundation; either
|
|
||||||
+ version 2.1 of the License, or (at your option) any later version.
|
|
||||||
+
|
|
||||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
||||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ Lesser General Public License for more details.
|
|
||||||
+
|
|
||||||
+ You should have received a copy of the GNU Lesser General Public
|
|
||||||
+ License along with the GNU C Library; if not, see
|
|
||||||
+ <http://www.gnu.org/licenses/>. */
|
|
||||||
+
|
|
||||||
+#include <support/check.h>
|
|
||||||
+#include <support/support.h>
|
|
||||||
+#include <string.h>
|
|
||||||
+#include <stdlib.h>
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+do_test (void)
|
|
||||||
+{
|
|
||||||
+ char *p = support_quote_string ("");
|
|
||||||
+ TEST_COMPARE (strlen (p), 0);
|
|
||||||
+ free (p);
|
|
||||||
+ p = support_quote_string ("X");
|
|
||||||
+ TEST_COMPARE (strlen (p), 1);
|
|
||||||
+ TEST_COMPARE (p[0], 'X');
|
|
||||||
+ free (p);
|
|
||||||
+
|
|
||||||
+ /* Check escaping of backslash-escaped characters, and lack of
|
|
||||||
+ escaping for other shell meta-characters. */
|
|
||||||
+ p = support_quote_string ("$()*?`@[]{}~\'\"X");
|
|
||||||
+ TEST_COMPARE (strcmp (p, "$()*?`@[]{}~\\'\\\"X"), 0);
|
|
||||||
+ free (p);
|
|
||||||
+
|
|
||||||
+ /* Check lack of escaping for letters and digits. */
|
|
||||||
+#define LETTERS_AND_DIGTS \
|
|
||||||
+ "abcdefghijklmnopqrstuvwxyz" \
|
|
||||||
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
|
|
||||||
+ "0123456789"
|
|
||||||
+ p = support_quote_string (LETTERS_AND_DIGTS "@");
|
|
||||||
+ TEST_COMPARE (strcmp (p, LETTERS_AND_DIGTS "@"), 0);
|
|
||||||
+ free (p);
|
|
||||||
+
|
|
||||||
+ /* Check escaping of control characters and other non-printable
|
|
||||||
+ characters. */
|
|
||||||
+ p = support_quote_string ("\r\n\t\a\b\f\v\1\177\200\377@");
|
|
||||||
+ TEST_COMPARE (strcmp (p, "\\r\\n\\t\\a\\b\\f\\v\\001"
|
|
||||||
+ "\\177\\200\\377@"), 0);
|
|
||||||
+ free (p);
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#include <support/test-driver.c>
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user