XkbCopyKeymap: be more careful with levels, allocate compat/geom
Take various extra precautions with copying levels across (thanks Chris Lee for a gdb session), including allocating when we don't already have a coherent map. Only free type components if they're present. Allocate geometry and compat components if we don't already have them in the dest map.
This commit is contained in:
parent
d7d931abe0
commit
d9a5e3e964
|
@ -1082,28 +1082,39 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
|
||||||
stype = src->map->types;
|
stype = src->map->types;
|
||||||
dtype = dst->map->types;
|
dtype = dst->map->types;
|
||||||
for (i = 0; i < src->map->num_types; i++, dtype++, stype++) {
|
for (i = 0; i < src->map->num_types; i++, dtype++, stype++) {
|
||||||
if (stype->num_levels != dtype->num_levels) {
|
if (stype->num_levels) {
|
||||||
if (dtype->level_names)
|
if (stype->num_levels != dtype->num_levels &&
|
||||||
|
dtype->num_levels && dtype->level_names) {
|
||||||
tmp = xrealloc(dtype->level_names,
|
tmp = xrealloc(dtype->level_names,
|
||||||
stype->num_levels * sizeof(Atom));
|
stype->num_levels * sizeof(Atom));
|
||||||
else
|
if (!tmp)
|
||||||
|
continue;
|
||||||
|
dtype->level_names = tmp;
|
||||||
|
}
|
||||||
|
else if (!dtype->num_levels || !dtype->level_names) {
|
||||||
tmp = xalloc(stype->num_levels * sizeof(Atom));
|
tmp = xalloc(stype->num_levels * sizeof(Atom));
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
continue; /* don't return FALSE here, try to whack
|
continue;
|
||||||
all the pointers we can, so we don't
|
|
||||||
double-free when going down. */
|
|
||||||
dtype->level_names = tmp;
|
dtype->level_names = tmp;
|
||||||
dtype->num_levels = stype->num_levels;
|
|
||||||
}
|
}
|
||||||
|
dtype->num_levels = stype->num_levels;
|
||||||
memcpy(dtype->level_names, stype->level_names,
|
memcpy(dtype->level_names, stype->level_names,
|
||||||
stype->num_levels * sizeof(Atom));
|
stype->num_levels * sizeof(Atom));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (dtype->num_levels && dtype->level_names)
|
||||||
|
xfree(dtype->level_names);
|
||||||
|
dtype->num_levels = 0;
|
||||||
|
dtype->level_names = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
dtype->name = stype->name;
|
dtype->name = stype->name;
|
||||||
memcpy(&dtype->mods, &stype->mods, sizeof(XkbModsRec));
|
memcpy(&dtype->mods, &stype->mods, sizeof(XkbModsRec));
|
||||||
|
|
||||||
|
if (stype->map_count) {
|
||||||
if (stype->map) {
|
if (stype->map) {
|
||||||
if (dtype->map) {
|
if (stype->map_count != dtype->map_count &&
|
||||||
if (stype->map_count != dtype->map_count) {
|
dtype->map_count && dtype->map) {
|
||||||
tmp = xrealloc(dtype->map,
|
tmp = xrealloc(dtype->map,
|
||||||
stype->map_count *
|
stype->map_count *
|
||||||
sizeof(XkbKTMapEntryRec));
|
sizeof(XkbKTMapEntryRec));
|
||||||
|
@ -1111,8 +1122,7 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
dtype->map = tmp;
|
dtype->map = tmp;
|
||||||
}
|
}
|
||||||
}
|
else if (!dtype->map_count || !dtype->map) {
|
||||||
else {
|
|
||||||
tmp = xalloc(stype->map_count *
|
tmp = xalloc(stype->map_count *
|
||||||
sizeof(XkbKTMapEntryRec));
|
sizeof(XkbKTMapEntryRec));
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
|
@ -1120,14 +1130,13 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
|
||||||
dtype->map = tmp;
|
dtype->map = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
dtype->map_count = stype->map_count;
|
memcpy(dtype->map, stype->map,
|
||||||
memcpy(dtype->map, stype->map, stype->map_count *
|
stype->map_count * sizeof(XkbKTMapEntryRec));
|
||||||
sizeof(XkbKTMapEntryRec));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stype->preserve) {
|
if (stype->preserve) {
|
||||||
if (dtype->preserve) {
|
if (stype->map_count != dtype->map_count &&
|
||||||
if (stype->map_count != dtype->map_count) {
|
dtype->map_count && dtype->preserve) {
|
||||||
tmp = xrealloc(dtype->preserve,
|
tmp = xrealloc(dtype->preserve,
|
||||||
stype->map_count *
|
stype->map_count *
|
||||||
sizeof(XkbModsRec));
|
sizeof(XkbModsRec));
|
||||||
|
@ -1135,9 +1144,9 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
dtype->preserve = tmp;
|
dtype->preserve = tmp;
|
||||||
}
|
}
|
||||||
}
|
else if (!dtype->preserve || !dtype->map_count) {
|
||||||
else {
|
tmp = xalloc(stype->map_count *
|
||||||
tmp = xalloc(stype->map_count * sizeof(XkbModsRec));
|
sizeof(XkbModsRec));
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
dtype->preserve = tmp;
|
dtype->preserve = tmp;
|
||||||
|
@ -1146,11 +1155,19 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
|
||||||
memcpy(dtype->preserve, stype->preserve,
|
memcpy(dtype->preserve, stype->preserve,
|
||||||
stype->map_count * sizeof(XkbModsRec));
|
stype->map_count * sizeof(XkbModsRec));
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
if (dtype->preserve) {
|
dtype->map_count = stype->map_count;
|
||||||
xfree(dtype->preserve);
|
|
||||||
dtype->preserve = NULL;
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
if (dtype->map_count) {
|
||||||
|
if (dtype->map)
|
||||||
|
xfree(dtype->map);
|
||||||
|
if (dtype->preserve)
|
||||||
|
xfree(dtype->preserve);
|
||||||
|
dtype->map_count = 0;
|
||||||
|
}
|
||||||
|
dtype->map = NULL;
|
||||||
|
dtype->preserve = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1160,9 +1177,9 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
|
||||||
i++, dtype++) {
|
i++, dtype++) {
|
||||||
if (dtype->level_names)
|
if (dtype->level_names)
|
||||||
xfree(dtype->level_names);
|
xfree(dtype->level_names);
|
||||||
if (dtype->map)
|
if (dtype->map && dtype->map_count)
|
||||||
xfree(dtype->map);
|
xfree(dtype->map);
|
||||||
if (dtype->preserve)
|
if (dtype->preserve && dtype->preserve)
|
||||||
xfree(dtype->preserve);
|
xfree(dtype->preserve);
|
||||||
}
|
}
|
||||||
xfree(dst->map->types);
|
xfree(dst->map->types);
|
||||||
|
@ -1451,6 +1468,12 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
|
||||||
|
|
||||||
/* compat */
|
/* compat */
|
||||||
if (src->compat) {
|
if (src->compat) {
|
||||||
|
if (!dst->compat) {
|
||||||
|
dst->compat = xcalloc(1, sizeof(XkbCompatMapRec));
|
||||||
|
if (!dst->compat)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (src->compat->sym_interpret) {
|
if (src->compat->sym_interpret) {
|
||||||
if (src->compat->size_si != dst->compat->size_si) {
|
if (src->compat->size_si != dst->compat->size_si) {
|
||||||
if (dst->compat->sym_interpret)
|
if (dst->compat->sym_interpret)
|
||||||
|
@ -1486,6 +1509,12 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
|
||||||
|
|
||||||
/* geometry */
|
/* geometry */
|
||||||
if (src->geom) {
|
if (src->geom) {
|
||||||
|
if (!dst->geom) {
|
||||||
|
dst->geom = xcalloc(sizeof(XkbGeometryRec), 1);
|
||||||
|
if (!dst->geom)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* properties */
|
/* properties */
|
||||||
if (src->geom->num_properties) {
|
if (src->geom->num_properties) {
|
||||||
if (src->geom->num_properties != dst->geom->sz_properties) {
|
if (src->geom->num_properties != dst->geom->sz_properties) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user