Commit 3f9321e7 authored by Andre Maroneze's avatar Andre Maroneze

adding Accel

parent edc1ec3b
directory file line function property kind status property
. 3dc.c 44 cgc_Push precondition of memcpy Unknown valid_dest: valid_or_empty(dest, n)
. 3dc.c 47 cgc_Push initialization Unknown \initialized(px_list_0 + i)
. 3dc.c 47 cgc_Push mem_access Unknown \valid_read(px_list_0 + i)
. 3dc.c 61 cgc_RunTask initialization Unknown \initialized(px_list_0 + tmp)
. 3dc.c 61 cgc_RunTask mem_access Unknown \valid_read(px_list_0 + tmp)
. 3dc.c 78 cgc_ReadFile mem_access Unknown \valid(&px->x)
. 3dc.c 105 cgc_NewFile initialization Unknown \initialized(px_list_0 + tmp_0)
. 3dc.c 105 cgc_NewFile mem_access Unknown \valid_read(px_list_0 + tmp_0)
. 3dc.c 107 cgc_NewFile precondition of memcpy Unknown valid_dest: valid_or_empty(dest, n)
. 3dc.c 110 cgc_NewFile precondition of memcpy Unknown valid_dest: valid_or_empty(dest, n)
. 3dc.c 113 cgc_NewFile precondition of memcpy Unknown valid_dest: valid_or_empty(dest, n)
. 3dc.c 116 cgc_NewFile precondition of memcpy Unknown valid_dest: valid_or_empty(dest, n)
. 3dc.c 119 cgc_NewFile precondition of memcpy Unknown valid_dest: valid_or_empty(dest, n)
. 3dc.c 122 cgc_NewFile precondition of memcpy Unknown valid_dest: valid_or_empty(dest, n)
. 3dc.c 125 cgc_NewFile precondition of memcpy Unknown valid_dest: valid_or_empty(dest, n)
. 3dc.c 136 cgc_ShowPixel initialization Unknown \initialized(&px->x)
. 3dc.c 136 cgc_ShowPixel initialization Unknown \initialized(&px->y)
. 3dc.c 136 cgc_ShowPixel initialization Unknown \initialized(&px->z)
. 3dc.c 136 cgc_ShowPixel mem_access Unknown \valid_read(&px->z)
. 3dc.c 137 cgc_ShowPixel initialization Unknown \initialized(&px->a)
. 3dc.c 137 cgc_ShowPixel initialization Unknown \initialized(&px->b)
. 3dc.c 137 cgc_ShowPixel initialization Unknown \initialized(&px->g)
. 3dc.c 137 cgc_ShowPixel initialization Unknown \initialized(&px->r)
. 3dc.c 149 cgc_CheckFile initialization Unknown \initialized(&(*(px + i))->x)
. 3dc.c 149 cgc_CheckFile initialization Unknown \initialized(&(*(px + i))->y)
. 3dc.c 149 cgc_CheckFile initialization Unknown \initialized(&(*(px + i))->z)
. 3dc.c 149 cgc_CheckFile initialization Unknown \initialized(px + i)
. 3dc.c 149 cgc_CheckFile mem_access Unknown \valid_read(&(*(px + i))->z)
. 3dc.c 150 cgc_CheckFile initialization Unknown \initialized(&(*(px + i))->a)
. 3dc.c 150 cgc_CheckFile initialization Unknown \initialized(&(*(px + i))->b)
. 3dc.c 150 cgc_CheckFile initialization Unknown \initialized(&(*(px + i))->g)
. 3dc.c 150 cgc_CheckFile initialization Unknown \initialized(&(*(px + i))->r)
. 3dc.c 150 cgc_CheckFile mem_access Unknown \valid_read(&(*(px + i))->a)
. 3dc.c 161 cgc_RotateX initialization Unknown \initialized(&px->y)
. 3dc.c 161 cgc_RotateX mem_access Unknown \valid_read(&px->y)
. 3dc.c 161 cgc_RotateX initialization Unknown \initialized(&px->z)
. 3dc.c 162 cgc_RotateX initialization Unknown \initialized(&px->y)
. 3dc.c 170 cgc_RotateY initialization Unknown \initialized(&px->z)
. 3dc.c 170 cgc_RotateY mem_access Unknown \valid_read(&px->z)
. 3dc.c 170 cgc_RotateY initialization Unknown \initialized(&px->x)
. 3dc.c 171 cgc_RotateY initialization Unknown \initialized(&px->x)
. 3dc.c 179 cgc_RotateZ initialization Unknown \initialized(&px->x)
. 3dc.c 179 cgc_RotateZ mem_access Unknown \valid_read(&px->x)
. 3dc.c 179 cgc_RotateZ initialization Unknown \initialized(&px->y)
. 3dc.c 180 cgc_RotateZ initialization Unknown \initialized(&px->x)
. 3dc.c 186 cgc_SkewX initialization Unknown \initialized(&px->x)
. 3dc.c 186 cgc_SkewX mem_access Unknown \valid(&px->x)
. 3dc.c 190 cgc_SkewY initialization Unknown \initialized(&px->y)
. 3dc.c 190 cgc_SkewY mem_access Unknown \valid(&px->y)
. 3dc.c 194 cgc_SkewZ initialization Unknown \initialized(&px->z)
. 3dc.c 194 cgc_SkewZ mem_access Unknown \valid(&px->z)
. 3dc.c 206 cgc_Scale initialization Unknown \initialized(&px->x)
. 3dc.c 206 cgc_Scale mem_access Unknown \valid_read(&px->x)
. 3dc.c 207 cgc_Scale initialization Unknown \initialized(&px->y)
. 3dc.c 208 cgc_Scale initialization Unknown \initialized(&px->z)
. 3dc.c 250 cgc_Brightness initialization Unknown \initialized(&px->r)
. 3dc.c 250 cgc_Brightness mem_access Unknown \valid_read(&px->r)
. 3dc.c 251 cgc_Brightness initialization Unknown \initialized(&px->g)
. 3dc.c 252 cgc_Brightness initialization Unknown \initialized(&px->b)
. 3dc.c 284 cgc_Opacity mem_access Unknown \valid(&px->a)
. compress.c 83 cgc_Compress initialization Unknown \initialized(px_list_0 + tmp)
. compress.c 83 cgc_Compress mem_access Unknown \valid_read(px_list_0 + tmp)
. compress.c 83 cgc_Compress signed_overflow Unknown p_idx + 1 ≤ 2147483647
. compress.c 85 cgc_Compress initialization Unknown \initialized(&px->r)
. compress.c 85 cgc_Compress mem_access Unknown \valid_read(&px->r)
. compress.c 88 cgc_Compress initialization Unknown \initialized(&px->g)
. compress.c 91 cgc_Compress initialization Unknown \initialized(&px->b)
. compress.c 93 cgc_Compress precondition of memcpy Unknown valid_dest: valid_or_empty(dest, n)
. compress.c 96 cgc_Compress precondition of memcpy Unknown valid_dest: valid_or_empty(dest, n)
. compress.c 99 cgc_Compress precondition of memcpy Unknown valid_dest: valid_or_empty(dest, n)
. compress.c 102 cgc_Compress precondition of memcpy Unknown valid_dest: valid_or_empty(dest, n)
. compress.c 121 cgc_Decompress precondition of memcpy Unknown valid_dest: valid_or_empty(dest, n)
. compress.c 121 cgc_Decompress precondition of memcpy Unknown valid_src: valid_read_or_empty(src, n)
. compress.c 125 cgc_Decompress precondition of memcpy Unknown valid_dest: valid_or_empty(dest, n)
. compress.c 125 cgc_Decompress precondition of memcpy Unknown valid_src: valid_read_or_empty(src, n)
. compress.c 129 cgc_Decompress precondition of memcpy Unknown valid_dest: valid_or_empty(dest, n)
. compress.c 129 cgc_Decompress precondition of memcpy Unknown valid_src: valid_read_or_empty(src, n)
. compress.c 133 cgc_Decompress initialization Unknown \initialized(in_data + tmp)
. compress.c 133 cgc_Decompress mem_access Unknown \valid_read(in_data + tmp)
. compress.c 144 cgc_Decompress mem_access Unknown \valid(out_data + tmp_0)
. compress.c 145 cgc_Decompress mem_access Unknown \valid(out_data + tmp_1)
. compress.c 146 cgc_Decompress mem_access Unknown \valid(out_data + tmp_2)
. compress.c 148 cgc_Decompress mem_access Unknown \valid(out_data + tmp_3)
. compress.c 169 cgc_WriteOut initialization Unknown \initialized(px_list_0 + i)
. compress.c 169 cgc_WriteOut mem_access Unknown \valid_read(px_list_0 + i)
. compress.c 173 cgc_WriteOut precondition of memcpy Unknown valid_dest: valid_or_empty(dest, n)
. compress.c 173 cgc_WriteOut precondition of memcpy Unknown valid_src: valid_read_or_empty(src, n)
. compress.c 175 cgc_WriteOut precondition of memcpy Unknown valid_dest: valid_or_empty(dest, n)
. compress.c 175 cgc_WriteOut precondition of memcpy Unknown valid_src: valid_read_or_empty(src, n)
. compress.c 177 cgc_WriteOut precondition of memcpy Unknown valid_dest: valid_or_empty(dest, n)
. compress.c 177 cgc_WriteOut precondition of memcpy Unknown valid_src: valid_read_or_empty(src, n)
. compress.c 179 cgc_WriteOut mem_access Unknown \valid(&tmp->a)
. main.c 80 cgc_menu precondition of memset Unknown valid_s: valid_or_empty(s, n)
. main.c 107 cgc_menu initialization Unknown \initialized(&coord)
. main.c 109 cgc_menu initialization Unknown \initialized(&val)
. main.c 112 cgc_menu initialization Unknown \initialized(&val)
. main.c 115 cgc_menu initialization Unknown \initialized(&val)
. main.c 128 cgc_menu initialization Unknown \initialized(&coord)
. main.c 130 cgc_menu initialization Unknown \initialized(&val)
. main.c 133 cgc_menu initialization Unknown \initialized(&val)
. main.c 136 cgc_menu initialization Unknown \initialized(&val)
. main.c 148 cgc_menu initialization Unknown \initialized(&val)
. main.c 155 cgc_menu initialization Unknown \initialized(&val)
. main.c 162 cgc_menu initialization Unknown \initialized(&val)
. main.c 185 cgc_menu precondition of memcpy Unknown valid_dest: valid_or_empty(dest, n)
. main.c 185 cgc_menu precondition of memcpy Unknown valid_src: valid_read_or_empty(src, n)
. main.c 197 cgc_menu initialization Unknown \initialized(&val)
. main.c 200 cgc_menu initialization Unknown \initialized(px_list_0 + val)
. main.c 200 cgc_menu mem_access Unknown \valid_read(px_list_0 + val)
. main.c 200 cgc_menu precondition of memcpy Unknown valid_dest: valid_or_empty(dest, n)
. main.c 200 cgc_menu precondition of memcpy Unknown valid_src: valid_read_or_empty(src, n)
/home/andr/git/oscs-pub3/cgc-challenges/lib libcgc.c 42 cgc_receive precondition of read Unknown buf_has_room: \valid((char *)buf + (0 .. count - 1))
FRAMAC_SHARE/libc string.h 92 memcpy precondition Unknown valid_dest: valid_or_empty(dest, n)
FRAMAC_SHARE/libc string.h 93 memcpy precondition Unknown valid_src: valid_read_or_empty(src, n)
FRAMAC_SHARE/libc string.h 115 memset precondition Unknown valid_s: valid_or_empty(s, n)
FRAMAC_SHARE/libc unistd.h 1005 read precondition Unknown buf_has_room: \valid((char *)buf + (0 .. count - 1))
[metrics] Eva coverage statistics
=======================
Syntactically reachable functions = 28 (out of 41)
Semantically reached functions = 28
Coverage estimation = 100.0%
[metrics] References to non-analyzed functions
------------------------------------
[metrics] Statements analyzed by Eva
--------------------------
545 stmts in analyzed functions, 530 stmts analyzed (97.2%)
cgc_Brightness: 25 stmts out of 25 (100.0%)
cgc_CheckFile: 14 stmts out of 14 (100.0%)
cgc_ClosestMatch: 29 stmts out of 29 (100.0%)
cgc_Compress: 37 stmts out of 37 (100.0%)
cgc_Decompress: 41 stmts out of 41 (100.0%)
cgc_NewFile: 29 stmts out of 29 (100.0%)
cgc_Opacity: 2 stmts out of 2 (100.0%)
cgc_ReadFile: 33 stmts out of 33 (100.0%)
cgc_RotateX: 27 stmts out of 27 (100.0%)
cgc_RotateY: 27 stmts out of 27 (100.0%)
cgc_RotateZ: 27 stmts out of 27 (100.0%)
cgc_RunTask: 17 stmts out of 17 (100.0%)
cgc_ShowPixel: 4 stmts out of 4 (100.0%)
cgc_SkewX: 2 stmts out of 2 (100.0%)
cgc_SkewY: 2 stmts out of 2 (100.0%)
cgc_SkewZ: 2 stmts out of 2 (100.0%)
cgc_WriteOut: 21 stmts out of 21 (100.0%)
cgc_degree_to_radian: 6 stmts out of 6 (100.0%)
cgc_divide: 2 stmts out of 2 (100.0%)
cgc_multiply: 2 stmts out of 2 (100.0%)
cgc_receive: 9 stmts out of 9 (100.0%)
main: 4 stmts out of 4 (100.0%)
receive_bytes_iPcz: 18 stmts out of 18 (100.0%)
cgc_menu: 117 stmts out of 120 (97.5%)
cgc_Push: 15 stmts out of 18 (83.3%)
cgc_Scale: 18 stmts out of 27 (66.7%)
[kernel] warning: attempting to save on non-zero exit code: modifying filename into `/home/andr/git/oscs-pub3/cgc-challenges/3D_Image_Toolkit/.frama-c/3D_Image_Toolkit.eva/framac.sav.error'.
[metrics] Defined functions (35)
======================
cgc_Brightness (address taken) (0 call); cgc_CheckFile (1 call);
cgc_ClosestMatch (3 calls); cgc_Compress (1 call); cgc_Decompress (1 call);
cgc_NewFile (1 call); cgc_Opacity (address taken) (0 call);
cgc_Push (1 call); cgc_ReadFile (1 call);
cgc_RotateX (address taken) (0 call); cgc_RotateY (address taken) (0 call);
cgc_RotateZ (address taken) (0 call); cgc_RunTask (9 calls);
cgc_Scale (address taken) (0 call); cgc_ShowPixel (2 calls);
cgc_SkewX (address taken) (0 call); cgc_SkewY (address taken) (0 call);
cgc_SkewZ (address taken) (0 call); cgc_WriteOut (1 call);
cgc__terminate (0 call); cgc_allocate (0 call); cgc_check_timeout (1 call);
cgc_copy_cgc_fd_set (2 calls); cgc_copy_os_fd_set (2 calls);
cgc_deallocate (0 call); cgc_degree_to_radian (3 calls);
cgc_divide (2 calls); cgc_fdwait (0 call); cgc_menu (1 call);
cgc_multiply (16 calls); cgc_random (0 call); cgc_transmit (0 call);
cgc_try_init_prng (1 call); main (0 call); receive_bytes_iPcz (10 calls);
Undefined functions (6)
=======================
cgc_aes_get_bytes (1 call); cgc_init_prng (1 call);
cgc_initialize_flag_page (0 call); cgc_prng (7 calls); cgc_receive (1 call);
seed_prng (1 call);
'Extern' global variables (0)
=============================
Potential entry points (7)
==========================
cgc__terminate; cgc_allocate; cgc_deallocate; cgc_fdwait; cgc_random;
cgc_transmit; main;
Global metrics
==============
Sloc = 711
Decision point = 103
Global variables = 6
If = 86
Loop = 14
Goto = 32
Assignment = 270
Exit point = 35
Function = 41
Function call = 166
Pointer dereferencing = 123
Cyclomatic complexity = 138
/home/andr/git/oscs-pub3/cgc-challenges/Accel/accel.c:372:[kernel:typing:no-proto] warning: Calling function cgc_clear_stack that is declared without prototype.
Its formals will be inferred from actual arguments
[kernel] warning: attempting to save on non-zero exit code: modifying filename into `/home/andr/git/oscs-pub3/cgc-challenges/Accel/.frama-c/Accel.parse/framac.sav.error'.
# Makefile template for Frama-C/Eva case studies.
# For details and usage information, see the Frama-C User Manual.
### Prologue. Do not modify this block. #######################################
-include path.mk
FRAMAC ?= frama-c
include $(shell $(FRAMAC)-config -scripts)/prologue.mk
###############################################################################
# Edit below as needed. MACHDEP is mandatory. Suggested flags are optional.
MACHDEP = x86_32
## Preprocessing flags (for -cpp-extra-args)
CPPFLAGS += \
-DPATCHED \
-I../../lib \
## General flags
FCFLAGS += \
-add-symbolic-path=..:. \
-kernel-warn-key annot:missing-spec=abort \
-kernel-warn-key typing:implicit-function-declaration=abort \
-absolute-valid-range 0x4347C000-0x4347FFFF \
## Eva-specific flags
EVAFLAGS += \
-eva-warn-key builtins:missing-spec=abort \
## GUI-only flags
FCGUIFLAGS += \
## Analysis targets (suffixed with .eva)
TARGETS = Accel.eva
### Each target <t>.eva needs a rule <t>.parse with source files as prerequisites
Accel.parse: \
../../lib/common.c \
../../lib/libcgc.c \
../accel.c \
../accelfunc.c \
../accelio.c \
../atof.c \
../ftoa.c \
../itoa.c \
../main.c \
../queue.c \
../stack.c \
### Epilogue. Do not modify this block. #######################################
include $(shell $(FRAMAC)-config -scripts)/epilogue.mk
###############################################################################
../../frama-c-cgc-path.mk
\ No newline at end of file
# KPRCA-00013
### DARPA performer group
Kaprica Security (KPRCA)
## Description
Accel is a spreadsheet program that enables a user to store information in a table and calculate numerical formulas based on cell data. Similar to other familiar spreadsheet programs, Accel is meant to assist in organizing large amounts of data that have interdependencies. The functions provided will enable a user to complete most simple financial and arithmetic needs.
### Feature List
Command Line Operations:
-------------------------
**Literal Assignment
A0=1
A0=This is a string
**Formula Assignment
A1==SQRT(9)
A2==A1+97
A3==SIN(A2/A1)
Supported String Commands:
----------------------
CLEAR - Clears a cell
Accel:-$ CLEAR A3
REPR - Show the representation of a cell (helpful with formulas)
Accel:-$ REPR A2 --> =A1+97
SHOW - Show the value of a cell, either literal or computer
Accel:-S SHOW A2 --> 100
Accel:-S SHOW A0 --> This is a string
SHOW TABLE - Shows the contents of the entire table
Accel:-S SHOW TABLE
EXIT - Exits the program
Accel:-S EXIT
Supported Functions:
------------------------------------------------
AVG - Calculate the average of a list
COUNT - Count the number of items in a list
MAX - Return the largest value in a list
MEDIAN - Calculate the median of a list
MIN - Return the smallest value in a list
STDDEV - Calculate the standard deviation of a list
ABS - Return the absolute value of a number
COS - Calculate the cosine function of a number
LN - Caclualte the natural log of a number
LOG10 - Calculate a log base 10 of a number
POWER - Raise a number to a power
SIN - Calculate the sine function of a number
SQRT - Take the square root of a number
SUM - Return the summation of a list
Supported Operators
------------------------------------------------
+ - Addition
* - Multiplication
/ - Division
- - Subtraction
## Vulnerability
In infixtorpn (accel.c:453), an attacker supplied string is parsed into its components. Every time a function name is encountered, it is stored in an array and the index (func_idx) is incremented. The check to test if the array needs to be enlarged is off by one, because the index is incremented between the check and the store. This results in an overflow of the heap buffer, which can allow the attacker to control the heap metadata (size) of the next heap block. Attacker control is limited because the memory is initially set to zero and then incremented every time a comma occurs, but an attacker only needs to get the value to greater than 32 or so to cause a segmentation fault. The fault occurs because the free method will try to split the memory even though it has wrong metadata and overwrite pointers on the heap.
Also, there is an uninitialized variable vulnerability in handle_op_median, where sorted variable wasn't initialized before being cleared.
### Generic class of vulnerability
Generic type: Heap-buffer overflow
Uninitialized variable
### CWE classification
CWE-193: Off-by-one Error
CWE-457: Use of Uninitialized Variable
## Challenges
This cb is meant to be difficult to analyze. The program should provide complexities that are will take some work to reason about. The bug is similar, in that it's difficult to detect what is or isn't a heap overflow especially when dealing with an off-by-one error.
This diff is collapsed.
This diff is collapsed.
/*
* Copyright (c) 2014 Kaprica Security, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include "cgc_stdlib.h"
#include "cgc_string.h"
#include "cgc_ctype.h"
#include "cgc_accelio.h"
/* sides = 1, trim front
* sides = 2, trim back
* sides = 3, trim both
*/
int cgc_strtrim(char *str, size_t size, int sides)
{
int i, len;
len = strlen(str) + 1;
if (len > size)
return -1;
else if (len == 1)
return 0;
if (sides == TRIM_FRONT || sides == TRIM_ALL) {
char *tmp = str;
for (i = 0; i < len; i++, tmp++) {
if (strchr(WHITESPACE, *tmp) == NULL) {
memcpy(str, tmp, len - i);
break;
}
}
}
if ((sides == TRIM_BACK || sides == TRIM_ALL) && (len - 1 != 0)) {
for (i = len - 2; i >= 0 ; i--) {
if (strchr(WHITESPACE, str[i]) == NULL) {
str[i + 1] = '\0';
break;
} else if (i == 0) {
str[i] = '\0';
break;
}
}
}
return 0;
}
//row and col must be buffers of at least len 4
int cgc_valid_cell_id(char *input)
{
if (strlen(input) < 2)
return -1;
size_t i = 0, is_num = 0;
char row[3];
char col[3];
char delim = '\0';
char c = toupper(input[0]);
if (c < 'A' || c > 'Z')
return -1;
row[0] = c;
c = toupper(input[1]);
if (!(c >= 'A' && c <= 'Z') && !(c >= '0' && c <= '9' ))
return -1;
if (c >= '0' && c <= '9') {
col[is_num++] = c;
row[1] = '\0';
} else {
row[1] = c;
row[2] = '\0';
}
for (i = 2; i < 5; i++) {
if (input[i] == delim && is_num) {
col[is_num] = '\0';
return 0;
}
if (input[i] >= '0' && input[i] <= '9' && is_num < 2) {
col[is_num++] = input[i];
}
else {
return -1;
}
}
return -1;
}
//row and col must be buffers of at least len 4
int cgc_get_rowcol(char *input, char *row, char *col, char delim)
{
if (strlen(input) < 2)
return -1;
size_t i = 0, is_num = 0;
char c = toupper(input[0]);
if (c < 'A' || c > 'Z')
return -1;
row[0] = c;
c = toupper(input[1]);
if (!(c >= 'A' && c <= 'Z') && !(c >= '0' && c <= '9' ))
return -1;
if (c >= '0' && c <= '9') {
col[is_num++] = c;
row[1] = '\0';
} else {
row[1] = c;
row[2] = '\0';
}
for (i = 2; i < 5; i++) {
if (input[i] == delim && is_num) {
col[is_num] = '\0';
return 0;
}
if (input[i] >= '0' && input[i] <= '9' && is_num < 2) {
col[is_num++] = input[i];
}
else {
return -1;
}
}
return -1;
}
int cgc_sanitize_formula(char *formula, size_t size)
{
size_t i, j, len;
len = strlen(formula);
if (len > size)
return -1;
char *sanitized = calloc(1, size);
if (sanitized == NULL)
return -1;
for (i = 0, j=0; i < len; i++) {
if (strchr(WHITESPACE, formula[i]) == NULL)
sanitized[j++] = formula[i];
}
memcpy(formula, sanitized, size);
free(sanitized);
return 0;
}
/*
* Copyright (c) 2014 Kaprica Security, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include "cgc_stdlib.h"
#include "cgc_string.h"
#include "cgc_ctype.h"
#include "cgc_convert.h"
double cgc_atof(char *str, size_t size, int *bad_conversion)
{
if (str == NULL || strlen(str) >= size || strlen(str) == 0)
goto error;
double val = 0.0, exp = 0.0, dec_multiplier = 1.0;
int has_period = 0, has_exp = 0;
int negative = 1;
int num_dec = 0;
if (*str == '-') {
str++;
if (*str == '\0')
goto error;
negative = -1;
}
while (*str != '\0') {
if (*str >= '0' && *str <= '9') {
if (has_exp) {
exp = (exp * 10) + (*str - '0');
} else if (!has_period) {
val = (val * 10) + (*str - '0');
} else {
dec_multiplier *= 10;
num_dec++;
val += ((*str - '0') / dec_multiplier);
}
} else if (*str == '.') {
has_period++;
} else if (cgc_tolower(*str) == 'e') {
has_exp++;
} else {
goto error;
}
if (has_period > 1 || has_exp > 1)
goto error;
if (num_dec >= MAX_DEC)
goto done;
str++;
}
goto done;
error:
*bad_conversion = 1;
return 0.0;
done:
if (has_exp)
val *= pow(10, exp);
return val * negative;
}
#ifndef ACCEL_H_
#define ACCEL_H_
int cgc_init_sheet();
char *cgc_show_cell(char *cell_id, int is_repr, char* val_str, size_t size);
int cgc_set_cell(char *cell_id, char *cell_str, size_t size);
int cgc_clear_cell(char *cell_id);
void cgc_print_assigned_cells();
#endif /* ACCELL_H */
#include "cgc_stack.h"
#ifndef ACCELFUNC_H_
#define ACCELFUNC_H_
typedef double (*handle_op_t)(stack_t **args, int *is_bad_formula);
typedef struct {
const char *name;
handle_op_t function;
} operator_t;
double cgc_handle_op_avg(stack_t **args, int *is_bad_formula);
double cgc_handle_op_count(stack_t **args, int *is_bad_formula);
double cgc_handle_op_max(stack_t **args, int *is_bad_formula);
double cgc_handle_op_median(stack_t **args, int *is_bad_formula);
double cgc_handle_op_min(stack_t **args, int *is_bad_formula);
double cgc_handle_op_stddev(stack_t **args, int *is_bad_formula);
double cgc_handle_op_abs(stack_t **args, int *is_bad_formula);
double cgc_handle_op_add(stack_t **args, int *is_bad_formula);
double cgc_handle_op_cos(stack_t **args, int *is_bad_formula);
double cgc_handle_op_ln(stack_t **args, int *is_bad_formula);
double cgc_handle_op_log10(stack_t **args, int *is_bad_formula);
double cgc_handle_op_power(stack_t **args, int *is_bad_formula);
double cgc_handle_op_product(stack_t **args, int *is_bad_formula);
double cgc_handle_op_quotient(stack_t **args, int *is_bad_formula);
double cgc_handle_op_sin(stack_t **args, int *is_bad_formula);
double cgc_handle_op_sqrt(stack_t **args, int *is_bad_formula);
double cgc_handle_op_subtract(stack_t **args, int *is_bad_formula);
double cgc_handle_op_sum(stack_t **args, int *is_bad_formula);
#endif /* ACCELFUNC_H */
#ifndef ACCELIO_H_
#define ACCELIO_H_
#define TRIM_FRONT 1
#define TRIM_BACK 2
#define TRIM_ALL 3
#define WHITESPACE "\r\n\t "
int cgc_strtrim(char *str, size_t size, int sides);
int cgc_valid_cell_id(char *input);
int cgc_get_rowcol(char *input, char *row, char *col, char delim);
int cgc_sanitize_formula(char *formula, size_t size);
#endif /* ACCELIO_H */
#ifndef CONVERT_H_
#define CONVERT_H_
#define MAX_DEC 5
extern char *cgc_itoa(int value, char *str, size_t size);
extern char *cgc_ftoa(double value, char *str, size_t size);
extern double cgc_atof(char *str, size_t size, int *bad_conversion);
#endif /* CONVERT_H */
#ifndef QUEUE_H_
#define QUEUE_H_
typedef struct queue queue_t;