[Mesa-dev] [PATCH 1/4] common: Check for extensions before resolving symbols

Eric Engestrom eric.engestrom at imgtec.com
Tue May 2 15:05:08 UTC 2017


On Tuesday, 2017-05-02 11:52:06 +0100, Daniel Stone wrote:
> eglGetProcAddress is allowed to return any old garbage for symbols it
> doesn't know about. To avoid any mishaps, check for the appropriate
> extension presence (split into EGL client extension, EGL display
> extension, and GL extension, checks) before we look up any symbols
> through it.
> 
> The walk through the extension list is taken from libepoxy.
> 
> Signed-off-by: Daniel Stone <daniels at collabora.com>

I had essentially the same change locally (but only for egl, not gl) :)

A couple nit picks below, but this patch is:
Reviewed-by: Eric Engestrom <eric.engestrom at imgtec.com>

> ---
>  common.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++------------
>  1 file changed, 51 insertions(+), 12 deletions(-)
> 
> diff --git a/common.c b/common.c
> index 610ff87..bf2f78e 100644
> --- a/common.c
> +++ b/common.c
> @@ -1,5 +1,6 @@
>  /*
>   * Copyright (c) 2017 Rob Clark <rclark at redhat.com>
> + * Copyright © 2013 Intel Corporation

2013? Is that for the has_ext() code from libepoxy?

>   *
>   * Permission is hereby granted, free of charge, to any person obtaining a
>   * copy of this software and associated documentation files (the "Software"),
> @@ -23,6 +24,7 @@
>  
>  #include <errno.h>
>  #include <fcntl.h>
> +#include <stdbool.h>
>  #include <stdio.h>
>  #include <stdlib.h>
>  #include <string.h>
> @@ -78,6 +80,26 @@ const struct gbm * init_gbm(int drm_fd, int w, int h, uint64_t modifier)
>  	return &gbm;
>  }
>  
> +static bool has_ext(const char *extension_list, const char *ext)
> +{
> +	const char *ptr = extension_list;
> +	int len = strlen(ext);
> +
> +	if (ptr == NULL || *ptr == '\0')
> +		return false;
> +
> +	while (true) {
> +		ptr = strstr(ptr, ext);
> +		if (!ptr)
> +			return false;
> +
> +		if (ptr[len] == ' ' || ptr[len] == '\0')
> +			return true;
> +
> +		ptr += len;
> +	}
> +}
> +
>  int init_egl(struct egl *egl, const struct gbm *gbm)
>  {
>  	EGLint major, minor, n;
> @@ -96,19 +118,24 @@ int init_egl(struct egl *egl, const struct gbm *gbm)
>  		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
>  		EGL_NONE
>  	};
> +	const char *egl_exts_client, *egl_exts_dpy, *gl_exts;
> +
> +#define get_proc_client(name, ext) do { \
> +		if (has_ext(egl_exts_client, ext)) \
> +			egl->name = (void *)eglGetProcAddress(#name); \
> +	} while (0)
> +#define get_proc_dpy(name, ext) do { \
> +		if (has_ext(egl_exts_dpy, ext)) \
> +			egl->name = (void *)eglGetProcAddress(#name); \
> +	} while (0)
>  
> -#define get_proc(name) do { \
> -		egl->name = (void *)eglGetProcAddress(#name); \
> +#define get_proc_gl(name, ext) do { \
> +		if (has_ext(gl_exts, ext)) \
> +			egl->name = (void *)eglGetProcAddress(#name); \
>  	} while (0)
>  
> -	get_proc(eglGetPlatformDisplayEXT);
> -	get_proc(eglCreateImageKHR);
> -	get_proc(eglDestroyImageKHR);
> -	get_proc(glEGLImageTargetTexture2DOES);
> -	get_proc(eglCreateSyncKHR);
> -	get_proc(eglDestroySyncKHR);
> -	get_proc(eglWaitSyncKHR);
> -	get_proc(eglDupNativeFenceFDANDROID);
> +	egl_exts_client = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
> +	get_proc_client(eglGetPlatformDisplayEXT, "EGL_EXT_platform_base");
>  
>  	if (egl->eglGetPlatformDisplayEXT) {
>  		egl->display = egl->eglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_KHR,
> @@ -122,6 +149,14 @@ int init_egl(struct egl *egl, const struct gbm *gbm)
>  		return -1;
>  	}
>  
> +	egl_exts_dpy = eglQueryString(egl->display, EGL_EXTENSIONS);
> +	get_proc_dpy(eglCreateImageKHR, "EGL_KHR_image_base");
> +	get_proc_dpy(eglDestroyImageKHR, "EGL_KHR_image_base");
> +	get_proc_dpy(eglCreateSyncKHR, "EGL_KHR_fence_sync");
> +	get_proc_dpy(eglDestroySyncKHR, "EGL_KHR_fence_sync");
> +	get_proc_dpy(eglWaitSyncKHR, "EGL_KHR_fence_sync");
> +	get_proc_dpy(eglDupNativeFenceFDANDROID, "EGL_ANDROID_native_fence_sync");

Moving the extension name as a first param makes it more readable IMO,
as does dropping the quotes (using `#` in the macro):

	get_proc_dpy(EGL_KHR_image_base, eglCreateImageKHR);
	get_proc_dpy(EGL_KHR_image_base, eglDestroyImageKHR);
	get_proc_dpy(EGL_KHR_fence_sync, eglCreateSyncKHR);
	get_proc_dpy(EGL_KHR_fence_sync, eglDestroySyncKHR);
	get_proc_dpy(EGL_KHR_fence_sync, eglWaitSyncKHR);
	get_proc_dpy(EGL_ANDROID_native_fence_sync, eglDupNativeFenceFDANDROID);

> +
>  	printf("Using display %p with EGL version %d.%d\n",
>  			egl->display, major, minor);
>  
> @@ -129,7 +164,8 @@ int init_egl(struct egl *egl, const struct gbm *gbm)
>  	printf("EGL information:\n");
>  	printf("  version: \"%s\"\n", eglQueryString(egl->display, EGL_VERSION));
>  	printf("  vendor: \"%s\"\n", eglQueryString(egl->display, EGL_VENDOR));
> -	printf("  extensions: \"%s\"\n", eglQueryString(egl->display, EGL_EXTENSIONS));
> +	printf("  client extensions: \"%s\"\n", egl_exts_client);
> +	printf("  display extensions: \"%s\"\n", egl_exts_dpy);
>  	printf("===================================\n");
>  
>  	if (!eglBindAPI(EGL_OPENGL_ES_API)) {
> @@ -159,14 +195,17 @@ int init_egl(struct egl *egl, const struct gbm *gbm)
>  	/* connect the context to the surface */
>  	eglMakeCurrent(egl->display, egl->surface, egl->surface, egl->context);
>  
> +	gl_exts = (char *) glGetString(GL_EXTENSIONS);
>  	printf("OpenGL ES 2.x information:\n");
>  	printf("  version: \"%s\"\n", glGetString(GL_VERSION));
>  	printf("  shading language version: \"%s\"\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
>  	printf("  vendor: \"%s\"\n", glGetString(GL_VENDOR));
>  	printf("  renderer: \"%s\"\n", glGetString(GL_RENDERER));
> -	printf("  extensions: \"%s\"\n", glGetString(GL_EXTENSIONS));
> +	printf("  extensions: \"%s\"\n", gl_exts);
>  	printf("===================================\n");
>  
> +	get_proc_gl(glEGLImageTargetTexture2DOES, "GL_OES_EGL_image");
> +
>  	return 0;
>  }
>  
> -- 
> 2.12.2
> 


More information about the mesa-dev mailing list