From 2cc415417e722bdf360a63935f0beb24fb8fc047 Mon Sep 17 00:00:00 2001
From: Matthew Jordan <mjordan@digium.com>
Date: Tue, 17 Apr 2012 20:59:25 +0000
Subject: [PATCH] Fix places where a negative return from ftello could be used
 as invalid input

In a variety of locations in both reading and writing a file, the result
from the C library function ftello is used as input to other functions.  For
the parameters and functions in question, a negative value is invalid input.
This patch checks the return value from the ftello function to determine if
we were able to determine the current position in the file stream and, if not,
fail gracefully.

(issue ASTERISK-19655)
Reported by: Matt Jordan

Review: https://reviewboard.asterisk.org/r/1863/
........

Merged revisions 362355 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........

Merged revisions 362356 from http://svn.asterisk.org/svn/asterisk/branches/10


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@362358 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 funcs/func_env.c | 34 +++++++++++++++++++++++++++-------
 1 file changed, 27 insertions(+), 7 deletions(-)

diff --git a/funcs/func_env.c b/funcs/func_env.c
index e849816c3f..f413607e0d 100644
--- a/funcs/func_env.c
+++ b/funcs/func_env.c
@@ -509,7 +509,11 @@ static int file_read(struct ast_channel *chan, const char *cmd, char *data, stru
 
 		if (offset < 0) {
 			fseeko(ff, offset, SEEK_END);
-			offset = ftello(ff);
+			if ((offset = ftello(ff)) < 0) {
+				ast_log(AST_LOG_ERROR, "Cannot determine offset position of '%s': %s\n", args.filename, strerror(errno));
+				fclose(ff);
+				return -1;
+			}
 		}
 		if (length < 0) {
 			fseeko(ff, length, SEEK_END);
@@ -780,11 +784,15 @@ static int file_write(struct ast_channel *chan, const char *cmd, char *data, con
 
 		if (offset < 0) {
 			if (fseeko(ff, offset, SEEK_END)) {
-				ast_log(LOG_ERROR, "Cannot seek to offset: %s\n", strerror(errno));
+				ast_log(LOG_ERROR, "Cannot seek to offset of '%s': %s\n", args.filename, strerror(errno));
+				fclose(ff);
+				return -1;
+			}
+			if ((offset = ftello(ff)) < 0) {
+				ast_log(AST_LOG_ERROR, "Cannot determine offset position of '%s': %s\n", args.filename, strerror(errno));
 				fclose(ff);
 				return -1;
 			}
-			offset = ftello(ff);
 		}
 
 		if (length < 0) {
@@ -946,10 +954,13 @@ static int file_write(struct ast_channel *chan, const char *cmd, char *data, con
 			} else if (!strchr(args.options, 'd') && fwrite(format2term(newline_format), 1, strlen(format2term(newline_format)), ff) < strlen(format2term(newline_format))) {
 				ast_log(LOG_ERROR, "Short write?!!\n");
 			}
-			truncsize = ftello(ff);
+			if ((truncsize = ftello(ff)) < 0) {
+				ast_log(AST_LOG_ERROR, "Unable to determine truncate position of '%s': %s\n", args.filename, strerror(errno));
+			}
 			fclose(ff);
-			if (truncate(args.filename, truncsize)) {
-				ast_log(LOG_ERROR, "Unable to truncate file: %s\n", strerror(errno));
+			if (truncsize >= 0 && truncate(args.filename, truncsize)) {
+				ast_log(LOG_ERROR, "Unable to truncate file '%s': %s\n", args.filename, strerror(errno));
+				return -1;
 			}
 		} else {
 			int64_t offset_offset = (offset == 0 ? 0 : -1), length_offset = -1, flength, i, current_length = 0;
@@ -971,7 +982,11 @@ static int file_write(struct ast_channel *chan, const char *cmd, char *data, con
 				fclose(ff);
 				return -1;
 			}
-			flength = ftello(ff);
+			if ((flength = ftello(ff)) < 0) {
+				ast_log(AST_LOG_ERROR, "Cannot determine end position of file '%s': %s\n", args.filename, strerror(errno));
+				fclose(ff);
+				return -1;
+			}
 
 			/* For negative offset and/or negative length */
 			if (offset < 0 || length < 0) {
@@ -1116,6 +1131,11 @@ static int file_write(struct ast_channel *chan, const char *cmd, char *data, con
 					return -1;
 				}
 				while ((cur = ftello(ff)) < flength) {
+					if (cur < 0) {
+						ast_log(AST_LOG_ERROR, "Unable to determine last write position for '%s': %s\n", args.filename, strerror(errno));
+						fclose(ff);
+						return -1;
+					}
 					fseeko(ff, length_length - vlen, SEEK_CUR);
 					if (fread(fbuf, 1, sizeof(fbuf), ff) < sizeof(fbuf) && !feof(ff)) {
 						ast_log(LOG_ERROR, "Short read?!!\n");
-- 
GitLab